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. SolutionUse # %LOOKUP maps keys to values %REVERSE = reverse %LOOKUP; DiscussionThis 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 AlsoThe |