Reverse key order, value in array to hash conversion
Suppose I have an array of values, then the keys (the opposite of what a hash assignment was expected):
use strict;
use warnings;
use Data::Dump;
my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash = @arr;
dd \%hash;
Printing
{ 1 => "uno", 2 => "dos", 3 => "tres", 4 => "cuatro" }
Obviously, duplicate keys are removed when the hash is generated.
How can I change the order of the pairs of values used to build the hash?
I know I can write a C style loop:
for(my $i=1; $i<=$#arr; $i=$i+2){
$hash{$arr[$i]}=$arr[$i-1];
}
dd \%hash;
# { cuatro => 4, dos => 2, four => 4, one => 1, three => 3, tres => 3, two => 2, uno => 1 }
But that seems a little awkward. I'm looking for something more idiomatic Perl.
In Python, I would just do dict(zip(arr[1::2], arr[0::2]))
source to share
TLP has the correct answer, but another way to avoid dropping dup keys is to use a hash of arrays. I guess the reason for you is to reverse the array.
use strict;
use warnings;
use Data::Dump;
my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash;
push @{ $hash{$arr[$_]} }, $arr[$_ + 1] for grep { not $_ % 2 } 0 .. $#arr;
dd \%hash;
Output:
{
1 => ["one", "uno"],
2 => ["two", "dos"],
3 => ["three", "tres"],
4 => ["four", "cuatro"],
}
As suggested by ikegami in the comments, you can take a look at List :: Pairwise available for CPAN for a more readable solution:
use strict;
use warnings;
use Data::Dump;
use List::Pairwise qw( mapp );
my @arr = qw(1 one 2 two 3 three 4 four 1 uno 2 dos 3 tres 4 cuatro);
my %hash;
mapp { push @{ $hash{$a} }, $b } @arr;
dd \%hash;
source to share
TLP has the correct answer , if your array of values, keys are ready to go into a hash.
That said, if you want to process the key or value anyway, before going into the hash, I believe this is what I use:
while (my ($v, $k)=(shift @arr, shift @arr)) {
last unless defined $k;
# xform $k or $v in someway, like $k=~s/\s*$//; to strip trailing whitespace...
$hash{$k}=$v;
}
(Note - destructive for an array @arr
. If you want to use it @arr
for something else, make a copy of it first.)
source to share