athomason has asked for the wisdom of the Perl Monks concerning the following question:

I want to initialize a hash so that the keys are taken from an array, and each value is 0. I hoped this would work:
my @keynames = (qw/first second third fourth/); my %hash = map ($_, 0), @keynames;
But for some reason, %hash is then totally empty. I tried using {leftsquarebracket}$_, 0{rightsquarebracket} instead of ($_, 0), but that only gives me an array of references (erk, I dunno how to escape square brackets :). How can I do this?

As a bonus academic question, what's the best way to do the same thing, but using another array for the initialization values (i.e. not 0)?

Replies are listed 'Best First'.
Re: Using map to interlace an array
by mdillon (Priest) on May 15, 2000 at 11:43 UTC
    the way to do what you want is as follows:
    my @keynames = qw/first second third fourth/; my %hash = map { $_, 0 } @keynames;

    you can initialize a hash with values from an array as follows (this is called a hash slice):

    my @keynames = qw/first second third fourth/; my @squares = map { $_ ** 2 } (1 .. 4); my %hash; @hash{@keynames} = @squares;

    also, in your example, i don't think the hash is totally empty. it should have a single undefined element in $hash{0}. i believe this is because the map variant you were using was treating the final value from your list (i.e. '0') as the map code and overwriting that element in the hash with undef for every element in @keynames.

      Right on all counts, thanks. Good call about the undefined value, too; when I did a print %hash it only displayed a 0, which is consistent with that.
RE: Using map to interlace an array
by pandr (Acolyte) on May 15, 2000 at 18:13 UTC
    How about:
    my @keys = qw( key1 key2 key3 ); my %hash; map {$hash{$_}=0} @keys;
    If you want to zip two arrays into a hash, you could try
    @keys = qw( a b c ); @values = qw ( 1 2 3 ); my %hash; $hash{$_} = shift @values for @keys;
Re: Using map to interlace an array
by chromatic (Archbishop) on May 16, 2000 at 03:47 UTC
    map may be overkill for this. I'd use hash slices:
    my @keynames = (qw/first second third fourth/); my %hash; @hash{@keynames} = ('0') x @keynames;
RE: Using map to interlace an array
by turnstep (Parson) on May 15, 2000 at 19:23 UTC

    To answer your side question, you can create brackets in normal text (that is, NOT surronded by CODE tags) by specifying [ for the left bracket and ] for the right bracket. This should be in the page "Perl Monk Procedures", IMHO (hint, hint to you-know-who) :)