Инвертирование хэша

Проблема

Хэш связывает ключ с ассоциированным значением. У вас имеется кэш и значение, для которого требуется определить ключ.

Решение

Воспользуйтесь функцией 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



2013-09-10 17:05:19

Proverte kod v komentariyah gde pro list tam oshibki detskie




Оставить комментарий:
Ваше Имя:
Email:
Антибот: *  
Ваш комментарий: