hash value initializarion to zero ...

Discussion in 'Perl Misc' started by martin, Apr 19, 2006.

  1. martin

    martin Guest

    This is probably a simpel question, I am trying to intialize a large
    hash, the keys are single word strings and the values are numeric.
    I am wondering if there is a simple way to use two arrays to assign to
    values and keys respectively, as opposed to the usual means of

    let's say

    my %citieshash {'key1', value1, 'key2', value2, ........}



    if I have a large hash of 100 entries, let say this becomes awkward
    specially if I want to set all values to zero, initially.

    I tried %cities = ( );


    and then used a loop to scan from a file the keys, it works fine if all
    city names are present , but if not all keys/cities are present, and I
    want to do addition of values with += the compiler starts complaining.
    Is there a single shot approach to zero initialization and also to
    setting key values using an existing array.

    something like

    (keys %citieshash) = @some_array <-- I know this one does not work

    Thanks.
     
    martin, Apr 19, 2006
    #1
    1. Advertising

  2. martin

    Guest

    "martin" <> wrote:
    > This is probably a simpel question, I am trying to intialize a large
    > hash, the keys are single word strings and the values are numeric.
    > I am wondering if there is a simple way to use two arrays to assign to
    > values and keys respectively, as opposed to the usual means of
    >
    > let's say
    >
    > my %citieshash {'key1', value1, 'key2', value2, ........}


    Er, let's say something else!

    >
    > if I have a large hash of 100 entries, let say this becomes awkward
    > specially if I want to set all values to zero, initially.
    >
    > I tried %cities = ( );
    >
    > and then used a loop to scan from a file the keys, it works fine if all
    > city names are present , but if not all keys/cities are present, and I
    > want to do addition of values with += the compiler starts complaining.


    The compiler shouldn't complain if the missing value is on the left side
    of the +=. If it is on the right, then you could just use something like
    $foo+=$hash{$_}||0

    > Is there a single shot approach to zero initialization and also to
    > setting key values using an existing array.
    >
    > something like
    >
    > (keys %citieshash) = @some_array <-- I know this one does not work


    my %citieshash = map {$_, 0} @some_array;

    Xho

    --
    -------------------- http://NewsReader.Com/ --------------------
    Usenet Newsgroup Service $9.95/Month 30GB
     
    , Apr 19, 2006
    #2
    1. Advertising

  3. martin wrote:
    > This is probably a simpel question, I am trying to intialize a large
    > hash, the keys are single word strings and the values are numeric.
    > I am wondering if there is a simple way to use two arrays to assign to
    > values and keys respectively,


    Yes, it's called a hash slice:

    @hash{ @keys } = @values;

    > as opposed to the usual means of
    >
    > let's say
    >
    > my %citieshash {'key1', value1, 'key2', value2, ........}


    You could do something like this:

    my %citieshash = map { $keys{ $_ }, $values{ $_ } } 0 .. $#keys;

    > if I have a large hash of 100 entries, let say this becomes awkward
    > specially if I want to set all values to zero, initially.
    >
    > I tried %cities = ( );


    If the hash already has keys:

    $_ = 0 for %hash;

    Or:

    @hash{ @keys } = ( 0 ) x @keys;

    Or:

    my %hash = map { $_ => 0 } @keys;

    > and then used a loop to scan from a file the keys, it works fine if all
    > city names are present , but if not all keys/cities are present, and I
    > want to do addition of values with += the compiler starts complaining.


    It shouldn't.

    $ perl -le'
    use warnings;
    use strict;
    my %hash;
    $hash{ key } += 10;
    print $hash{ key };
    '
    10

    > Is there a single shot approach to zero initialization and also to
    > setting key values using an existing array.


    See above.


    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Apr 19, 2006
    #3
  4. martin wrote:
    > This is probably a simpel question, I am trying to intialize a large
    > hash, the keys are single word strings and the values are numeric.
    > I am wondering if there is a simple way to use two arrays to assign to
    > values and keys respectively,


    Yes, it's called a hash slice:

    @hash{ @keys } = @values;

    > as opposed to the usual means of
    >
    > let's say
    >
    > my %citieshash {'key1', value1, 'key2', value2, ........}


    You could do something like this:

    my %citieshash = map { $keys[ $_ ], $values[ $_ ] } 0 .. $#keys;

    > if I have a large hash of 100 entries, let say this becomes awkward
    > specially if I want to set all values to zero, initially.
    >
    > I tried %cities = ( );


    If the hash already has keys:

    $_ = 0 for %hash;

    Or:

    @hash{ @keys } = ( 0 ) x @keys;

    Or:

    my %hash = map { $_ => 0 } @keys;

    > and then used a loop to scan from a file the keys, it works fine if all
    > city names are present , but if not all keys/cities are present, and I
    > want to do addition of values with += the compiler starts complaining.


    It shouldn't.

    $ perl -le'
    use warnings;
    use strict;
    my %hash;
    $hash{ key } += 10;
    print $hash{ key };
    '
    10

    > Is there a single shot approach to zero initialization and also to
    > setting key values using an existing array.


    See above.


    John
    --
    use Perl;
    program
    fulfillment
     
    John W. Krahn, Apr 19, 2006
    #4
  5. martin

    DJ Stunks Guest

    martin wrote:

    > Is there a single shot approach to zero initialization and also to
    > setting key values using an existing array.


    I'm not totally clear on what you're up to, but I hope this helps:

    C:\tmp>cat -n tmp2.pl
    1 #!/usr/bin/perl
    2
    3 use strict;
    4 use warnings;
    5
    6 my @array = map { "key$_" } 0..9;
    7
    8 # Initialize hash to 0's
    9 my %cities = map { $_ => 0 } @array;
    10
    11 # Populate some members
    12 for my $key ( map { "key$_" } (6,2,7) ) {
    13 $cities{$key} = int rand 100;
    14 }
    15
    16 # Print resulting hash
    17 for my $key (sort keys %cities) {
    18 printf "%5s => %5s\n", $key, $cities{$key};
    19 }
    20
    21 __END__

    C:\tmp>tmp2.pl
    key0 => 0
    key1 => 0
    key2 => 23
    key3 => 0
    key4 => 0
    key5 => 0
    key6 => 13
    key7 => 39
    key8 => 0
    key9 => 0

    -jp
     
    DJ Stunks, Apr 19, 2006
    #5
  6. martin

    Anno Siegel Guest

    John W. Krahn <> wrote in comp.lang.perl.misc:
    > martin wrote:


    [...]

    > > if I have a large hash of 100 entries, let say this becomes awkward
    > > specially if I want to set all values to zero, initially.
    > >
    > > I tried %cities = ( );

    >
    > If the hash already has keys:
    >
    > $_ = 0 for %hash;


    That would have to be

    $_ = 0 for values %hash;

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Apr 19, 2006
    #6
  7. martin

    Paul Lalli Guest

    Anno Siegel wrote:
    > John W. Krahn <> wrote in comp.lang.perl.misc:
    > > If the hash already has keys:
    > >
    > > $_ = 0 for %hash;

    >
    > That would have to be
    >
    > $_ = 0 for values %hash;


    Did you try it?

    perl -MData::Dumper -e'
    my %h = (one=>1, two=>2, three=>3);
    $_ = 0 for %h;
    print Dumper(\%h);
    '
    $VAR1 = {
    'one' => 0,
    'three' => 0,
    'two' => 0
    };

    Looks like it works just fine to me. I can only assume this is due to
    the rather odd properties of a hash that the values returned are
    aliases, while the keys are copies.

    Paul Lalli
     
    Paul Lalli, Apr 19, 2006
    #7
  8. martin

    Anno Siegel Guest

    Paul Lalli <> wrote in comp.lang.perl.misc:
    > Anno Siegel wrote:
    > > John W. Krahn <> wrote in comp.lang.perl.misc:
    > > > If the hash already has keys:
    > > >
    > > > $_ = 0 for %hash;

    > >
    > > That would have to be
    > >
    > > $_ = 0 for values %hash;

    >
    > Did you try it?


    No. I simply assumed he'd forgotten "values".

    > perl -MData::Dumper -e'
    > my %h = (one=>1, two=>2, three=>3);
    > $_ = 0 for %h;
    > print Dumper(\%h);
    > '
    > $VAR1 = {
    > 'one' => 0,
    > 'three' => 0,
    > 'two' => 0
    > };
    >
    > Looks like it works just fine to me. I can only assume this is due to
    > the rather odd properties of a hash that the values returned are
    > aliases, while the keys are copies.


    I'd say "happens to work" instead of "works just fine". It relies on
    an obscure effect, and it does twice the necessary number of assignments.
    I'd still consider it an error in non-obfuscated code.

    Anno
    --
    If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers.
     
    Anno Siegel, Apr 19, 2006
    #8
  9. martin

    Uri Guttman Guest

    >>>>> "PL" == Paul Lalli <> writes:

    PL> Looks like it works just fine to me. I can only assume this is due to
    PL> the rather odd properties of a hash that the values returned are
    PL> aliases, while the keys are copies.

    you should know better about hash keys. you can never change an existing
    key as it would require a hashing of the new key. so that means
    modifying a key it is just an assignment to a hash slot. so there is no
    win to making the key modifyable. on the otherhand, the values are just
    normal SV's which means you can take refs to the, alias them in values
    (and foreach values also aliases) and change them on the fly.

    and slices and x work well here too:

    @hash{ keys %hash } = (0) x keys %hash ;

    you would think this also should work if values just aliased the hash
    values:

    perl -le '%h=(1,2,3,4) ;(values %h) = (0,0) ; print %h'
    Can't modify values in list assignment at -e line 1, near ") ;"

    uri

    --
    Uri Guttman ------ -------- http://www.stemsystems.com
    --Perl Consulting, Stem Development, Systems Architecture, Design and Coding-
    Search or Offer Perl Jobs ---------------------------- http://jobs.perl.org
     
    Uri Guttman, Apr 19, 2006
    #9
  10. martin

    Paul Lalli Guest

    Uri Guttman wrote:
    > >>>>> "PL" == Paul Lalli <> writes:

    >
    > PL> Looks like it works just fine to me. I can only assume this is due to
    > PL> the rather odd properties of a hash that the values returned are
    > PL> aliases, while the keys are copies.
    >
    > you should know better about hash keys. you can never change an existing
    > key as it would require a hashing of the new key. so that means
    > modifying a key it is just an assignment to a hash slot. so there is no
    > win to making the key modifyable. on the otherhand, the values are just
    > normal SV's which means you can take refs to the, alias them in values
    > (and foreach values also aliases) and change them on the fly.


    Thank you for that explanation, Uri. Much appreciated.

    Paul Lalli
     
    Paul Lalli, Apr 19, 2006
    #10
  11. Paul Lalli wrote:
    > Anno Siegel wrote:
    > > John W. Krahn <> wrote in comp.lang.perl.misc:
    > > > If the hash already has keys:
    > > >
    > > > $_ = 0 for %hash;

    > >
    > > That would have to be
    > >
    > > $_ = 0 for values %hash;

    >
    > Did you try it?


    Trying it is not always sufficient.

    ISTR that somewhere in the Perl documentation there was at one time an
    explicit warning that the fact that hash keys are not modifyable is
    subject to change in future versions of Perl. I don't think this is
    still there and so I'd be supprised if the keys were now ever to became
    modifyable.

    However by rights John's code should thow an "attempt to modify
    read-only value" and I'd be only slightly supprised if in some future
    version of Perl it actually did.
     
    Brian McCauley, Apr 19, 2006
    #11
  12. Uri Guttman wrote:
    >>>>>> "PL" == Paul Lalli <> writes:

    >
    > PL> Looks like it works just fine to me. I can only assume this is due to
    > PL> the rather odd properties of a hash that the values returned are
    > PL> aliases, while the keys are copies.
    >
    > you should know better about hash keys. you can never change an existing
    > key as it would require a hashing of the new key. so that means
    > modifying a key it is just an assignment to a hash slot. so there is no
    > win to making the key modifyable. on the otherhand, the values are just
    > normal SV's which means you can take refs to the, alias them in values
    > (and foreach values also aliases) and change them on the fly.
    >
    > and slices and x work well here too:
    >
    > @hash{ keys %hash } = (0) x keys %hash ;
    >
    > you would think this also should work if values just aliased the hash
    > values:
    >
    > perl -le '%h=(1,2,3,4) ;(values %h) = (0,0) ; print %h'
    > Can't modify values in list assignment at -e line 1, near ") ;"
    >


    Seems like the cleaner, faster idiom would be $_ = 0 for values %h
    instead of $_ = 0 for %h (even with 6 more keystokes) since the key
    assignments in the later are just throwaway's.


    --
    Charles DeRykus
     
    Charles DeRykus, Apr 20, 2006
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Zhiqiang Ye
    Replies:
    53
    Views:
    10,324
    Dan Pop
    Jun 28, 2004
  2. Gerard Flanagan
    Replies:
    3
    Views:
    458
    Terry Hancock
    Nov 19, 2005
  3. Christopher Benson-Manica

    Doubles and zero/negative zero

    Christopher Benson-Manica, Jun 30, 2004, in forum: C Programming
    Replies:
    4
    Views:
    688
    Walter
    Jul 1, 2004
  4. rp
    Replies:
    1
    Views:
    555
    red floyd
    Nov 10, 2011
  5. Une bévue
    Replies:
    5
    Views:
    155
    Une bévue
    Aug 10, 2006
Loading...

Share This Page