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!
Re: Combining two lists into a hash
by Paladin (Vicar) on May 03, 2005 at 21:31 UTC
|
my %hash;
@hash{@a} = @b;
| [reply] [d/l] |
Re: Combining two lists into a hash
by trammell (Priest) on May 03, 2005 at 21:32 UTC
|
my %result;
@result{ @keys } = @values;
| [reply] [d/l] |
Re: Combining two lists into a hash
by johnnywang (Priest) on May 03, 2005 at 21:32 UTC
|
my @a = ('one', 'two', 'three');
my @b = (1, 2, 3);
my %result;
@result{@a} = @b;
| [reply] [d/l] |
Re: Combining two lists into a hash
by ikegami (Patriarch) on May 03, 2005 at 21:36 UTC
|
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.
| [reply] [d/l] |
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
| [reply] [d/l] |
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;
| [reply] [d/l] |
|
| [reply] |
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. | [reply] |
|
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. | [reply] [d/l] [select] |
|
@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!
| [reply] [d/l] |
|
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.
| [reply] |
|
|