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]))

+3


source to share


3 answers


Use reverse

:

my %hash = reverse @arr;

      



Perl's built-in functions are listed in the perldoc perlfunc .

+8


source


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;

      

+4


source


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.)

0


source







All Articles