5.8. Inverting a HashProblemHashes map keys to values. You have a hash and a value for which you want to find the corresponding key. Solution
Use # %LOOKUP maps keys to values %REVERSE = reverse %LOOKUP; Discussion
This technique uses the list equivalence of hashes mentioned in the introduction. In list context, Here's an example:
%surname = ( "Mickey" => "Mantle", "Babe" => "Ruth" );
%first_name = reverse %surname;
print $first_name{"Mantle"}, "\n";
When we treat ("Mickey", "Mantle", "Babe", "Ruth")
(or maybe ("Ruth", "Babe", "Mantle", "Mickey") When we treat this list as a hash, it becomes: ("Ruth" => "Babe", "Mantle" => "Mickey") Now instead of turning first names into surnames, it turns surnames into first names.
Example 5.2
is a program called Example 5.2: foodfind#!/usr/bin/perl -w # foodfind - find match for food or color $given = shift @ARGV or die "usage: foodfind food_or_color\n"; %color = ( "Apple" => "red", "Banana" => "yellow", "Lemon" => "yellow", "Carrot" => "orange" ); %food = reverse %color; if (exists $color{$given}) { print "$given is a food with color $color{$given}.\n"; } if (exists $food{$given}) { print "$food{$given} is a food with color $given.\n"; }
If two keys in the original hash have the same value (as If you want to invert a hash with non-unique values, you must use the techniques shown in Recipe 5.7 . That is, build up a hash whose values are a list of keys in the original hash:
# %food_color as per the introduction
while (($food,$color) = each(%food_color)) {
push(@{$foods_with_color{$color}}, $food);
}
print "@{$foods_with_color{yellow}} were yellow foods.\n";
This also lets us change the If any values in the original hash were references instead of just strings and numbers, the inverted hash poses a problem because references don't work well as hash keys unless you use the Tie::RefHash module described in Recipe 5.12 . See Also
The |
|