Beefy Boxes and Bandwidth Generously Provided by pair Networks
go ahead... be a heretic
 
PerlMonks  

Combining two lists into a hash

by fthiess (Novice)
on May 03, 2005 at 21:28 UTC ( [id://453734]=perlquestion: print w/replies, xml ) Need Help??

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

Hi! I've got a spot where I need to combine two simple arrays into a hash, with the keys of the hash being elements of the first array, and the values corresponding to those keys being the elements of the second array. To illustrate the problem, here's a brute-force implementation:
my @a = ('one', 'two', 'three'); my @b = (1, 2, 3); my %result; for (my $i = 0; $i < scalar(@a); $i++) { $result{$a[$i]} = $b[$i]; }
This works, and does exactly what I want, but seems, well, "C-like". Can anyone offer me a more Perl-ish way to do this that is more esthetically pleasing?

Thanks!

Replies are listed 'Best First'.
Re: Combining two lists into a hash
by Paladin (Vicar) on May 03, 2005 at 21:31 UTC
Re: Combining two lists into a hash
by trammell (Priest) on May 03, 2005 at 21:32 UTC
    How about a hash slice:
    my %result; @result{ @keys } = @values;
Re: Combining two lists into a hash
by johnnywang (Priest) on May 03, 2005 at 21:32 UTC
    slices:
    my @a = ('one', 'two', 'three'); my @b = (1, 2, 3); my %result; @result{@a} = @b;
Re: Combining two lists into a hash
by ikegami (Patriarch) on May 03, 2005 at 21:36 UTC

    For variation from the hash slices posts:

    my @a = ('one', 'two', 'three'); my @b = (1, 2, 3); my %result = map { $a[$_] => $b[$_] } 0..$#a;

    I bet it's slower than a hash slice, though.

Re: Combining two lists into a hash
by NetWallah (Canon) on May 03, 2005 at 21:41 UTC
    Another, possibly more naive, but easier to understand alternative, with a distructive side-effect - but it works:
    my @a = ('one', 'two', 'three'); my @b = (1, 2, 3); my %h; $h{$_}=shift @b for @a; # Destroys @b - copy that if it needs saving
    Update:Thanks Fletch - fixed "h" to $h.

         "There are only two truly infinite things. The universe and stupidity, and I'm not too sure about the universe"- Albert Einstein

Re: Combining two lists into a hash
by dynamo (Chaplain) on May 03, 2005 at 21:40 UTC
    You can't get much more perlish than depending on the internal representation of hashes...

    instead of the for loop:

    my @temp = (); while (@a) { push @temp, shift @a, shift @b } %result = @temp;

      This does not depend on the internal representation of a hash. It simply takes advantage of the fact that a list can be coerced into a hash. That is documented behavior, not internal representation.

Re: Combining two lists into a hash
by scmason (Monk) on May 04, 2005 at 00:35 UTC
    Does perl-ish mean unreadable, less control over the output, or what? Maybe I am confused or out of my perl-brain, but I do not understand the desire to take perfectly working code that complies with the appearance/semantics of most other languages (C, C++, Java, Python etc) so that it complies with other peoples idea of what 'perl' should look like.

    Conformity for the sake of non-conformity?

    I think that your post is pointless.

      Perlish means taking advantage of perl control structures, data types, and abstractions. It means familiar to someone whose sole language is perl. That some of these perlish constructs look identical to constructs from other languages is not a problem. In fact, I'm sure that most of these constructs were stolen from those other languages anyway.

      Abstractions such as using:

      @hash{@a} = @b;
      instead of:
      for (my $i = 0; $i <= $#a; ++$i) { $hash{$a[$i]} = $b[$i]; }
      are not only much clearer and cleaner, they probably run faster, too. Perl can pre-allocate a full hash of the right size, meaning only a single allocation. It can really get in there, optimising speed and space, which the C-style code cannot do. In C-land, one would have to do all those optimisations by hand: you'd need an array object which kept track of the length (because counting the array to find the length takes too long for large arrays); you'd need a hash object which could be told to pre-allocate a certain amount of space; you'd need to also remember each time you go populate the hash to pre-allocate the amount of space you need to keep re-allocations to a minimum.

      In perl, all that extra overhead is handled for you. If you follow the perl idiom.

        @hash{@a} = @b;
        is exactly the sort of thing I was looking for! Several other great examples have been posted, which I also appreciate and which are enlightening in their own ways. This particular approach, though, is what I meant by "Perl-ish" and "esthetic": it's a higher-level way of implementing the function that is both less work for the programmer, and more clear for potential readers--the sort of thing that Perl can excel at, compared to a language like C of Java.

        Thanks, everyone!
      I think it's a good idea to learn/use the idioms of a language, especially if it provides simplicity and doesn't obfuscate code. I'd prefer to speak a language natively, rather than perl with a C accent. That being said, however, perl does allow more freedom to make itself write-only, each of us will have to appeal to our senses.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://453734]
Approved by tlm
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others chanting in the Monastery: (3)
As of 2024-04-20 02:54 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found