tags:

views:

84

answers:

2

I have a hash that looks like this:

{ bmw      => { id => 1, color => brown } }
{ mercedes => { id => 2, color => black } }

I want to reverse this hash in perl so that I just get a mapping of id => name_of_car. Do I need to use the reverse function somehow?

Note: I can always iterate through the original hash and assign the keys and values accordingly in the new hash, nut I wanted to know if there was a slicker way.

+4  A: 

Don't need a slick way:

my %h = (
    bmw      => { id => 1, color => "brown" } ,
    mercedes => { id => 2, color => "black" } 
);
my %j = map { ($h{$_}{id} => $_) } keys %h;

for (keys %j) {
    print "$_ $j{$_}\n";
}

Output:

$ ./silly.pl 
1 bmw
2 mercedes
Kinopiko
Hey, no need to be down on your solution. Your way looks pretty slick to me :).
masonk
This is just the usual way though.
Kinopiko
I see that we have different definitions of "slick"
masonk
+3  A: 

What you've posted is not valid perl, but I think I take your meaning. One slick way to do this would be with a hash slice and a map.

my %hash = (
    bmw      => { id => 1, color => 'brown' },
    mercedes => { id => 2, color => 'black' },
);
my %new_hash;
@new_hash{ map { $_->{id} } values %hash } = keys %hash;
masonk
Why is an alias (@) symbol used on the last line before new_hash?
syker
@syker: please look at the link masonk provided about "hash slice".
Kinopiko
This is special syntax for a hash slice (linked above). You provide a list of keys on the left hand side and a list of values on the right hand side. Perl guarantees that the order in which values %hash are returned is the same order as that in which keys %hash are returned, so this works.
masonk