Инвертирование хэша
Проблема
Хэш связывает ключ с ассоциированным значением.
У вас имеется кэш и значение, для которого требуется определить ключ.
Решение
Воспользуйтесь функцией
reverse
для создания инвертированного хэша, где ассоциированные
значения исходного хэша являются ключами, и наоборот.
# %ХЭШ связывает ключи со значениями
%ОБРАТНЫЙ = reverse %ХЭШ;
Комментарий
В этом решении используется списковая эквивалентность хэшей, о которой упоминалось во введении.
В списковом контексте reverse интерпретирует %ХЭШ как список и меняет местами составляющие его элементов.
Одно из важнейших свойств списковой интерпретации хэша заключается в том, что элементы списка
представляют собой пары «ключ/значение». После инвертирования такого списка первым
элементом становится значение, а вторым — ключ. Если интерпретировать такой список как хэш,
его значения будут являться ключами исходного хэша, и наоборот. Приведем пример:
%surname = ( "Mickey" => "Mantle", "Babe" => "Ruth" );
%first_name = reverse %surname;
print $first_name{"Mantle", "\n";
Mickey
Если интерпретировать %surname как список, мы получим следующее:
("Mickey", "Mantle", "Babe", "Ruth")
(а может быть,
("Babe", "Ruth", "Mickey", "Mantle"),
поскольку порядок элементов непредсказуем).
После инвертирования список выглядит так:
("Ruth", "Babe", "Mantle", "Mickey")
Интерпретация его в качестве хэша дает следующее:
("Ruth" => "Babe", "Mantle" => "Mickey")
Далее приведена программа foodfind. Если передать ей название продукта, она сообщает цвет,
а если передать цвет — она сообщает название.
# foodfind - поиск продуктов по названию или цвету
$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";
}
Если два ключа исходного хэша имеют одинаковые значения ("Lemon" и "Banana" в предыдущем примере),
то инвертированный хэш будет содержать лишь один из них (какой именно — зависит от порядка хэширования,
так что непредсказуемо). Дело в том, что хэши в Perl по определению имеют уникальные ключи.
Чтобы инвертировать хэш с повторяющимися значениями, следует построить хэш, ассоциированные
значения которого представляют собой списки ключей исходного хэша:
while (($food,$color) = each(%food_color)) {
push(@{foods_with_color{$color}}, $food);
}
print "@{$foods_with_color{yellow}} were yellowfoods. n";
Banana Lemon were yellow foods.
Кроме того, это позволит модифицировать программу foodfind так, чтобы она работала с
цветами, соответствующими сразу нескольким продуктам. Например, при вызове foodfind yellow
будут выводиться и Banana, и Lemon.
См. такжеОписание функций reverse
Proverte kod v komentariyah gde pro list tam oshibki detskie
Оставить комментарий:
|
|