Читаем Язык программирования Perl полностью

Следует помнить, что если размер хэша велик, то и полученный с помощью функции keys массив ключей тоже будет занимать большой объем памяти. В скалярном контексте функция keys возвращает количество ключей в хэше, поэтому с ее помощью можно легко проверить, не пустой ли хэш:

if (keys %hash) { # если scalar(keys(%hash)) != 0 # обработать элементы хэша, если он не пуст }

Пустой хэш в скалярном контексте возвращает ложное значение (строку '0'), а непустой - истинное. Поэтому проверить, пуст ли хэш, можно еще проще - употребив имя хэша в скалярном контексте, что часто используется в конструкциях, проверяющих условие:

while (%hash) { # или scalar(%hash) != 0 (не пуст ли хэш?) # обработать элементы хэша }

Встроенная функция values, дополняющая функцию keys, возвращает список всех значений элементов хэша в том же порядке, в каком функция keys возвращает ключи. С полученным списком можно поступать обычным образом: например, сохранить в массиве или обработать в цикле:

@hash_values = values %hash; # сохранить все значения хэша print "$_\n" foreach (values %hash); # вывести значения

В скалярном контексте функция values возвращает количество значений в хэше, так что ее можно использовать для того, чтобы узнать размер хэша. Например:

$hash_size = values %hash; # число значений в хэше

Функция each является встроенным итератором - программной конструкцией, контролирующей последовательную обработку элементов какой-либо коллекции данных. Она предоставляет возможность последовательно обработать все ассоциативные пары в хэше, организуя перебор всех его элементов. При каждом вызове она возвращает двухэлементный список, состоящий из очередного ключа и значения из хэша. Пары элементов возвращаются в неизвестном заранее порядке.

($key, $value) = each %hash; # взять очередную пару элементов

После того как будет возвращена последняя пара элементов хэша, функция each возвращает пустой список. После этого следующий вызов each начнет перебор элементов хэша сначала. С ее помощью удобно организовать обработку всех элементов хэша в цикле, который закончится, когда each вернет пустой список, означающий "ложь":

while (my ($key, $value) = each %hash) { # пока есть пары # обработать очередные ключ и значение хэша print "с ключом $key связано значение $value\n"; }

Иногда требуется искать ключи хэша по их значениям. Для этого нужно создать обратный ассоциативный массив (или инвертированный хэш), поменяв местами значения и ключи хэша. Это можно сделать так:

while (my ($key, $value) = each %hash_by_key) { # ключи хэша $hash_by_value{$value} = $key; # становятся значениями }

Этого же результата можно достичь с помощью функции reverse, воспользовавшись тем, что она воспринимает хэш как список, в котором за каждым ключом идет значение, и меняет порядок всех элементов этого списка на обратный. Функция reverse возвращает список, в котором в каждой паре элементов за значением следует ключ, и этот список присваивается новому хэшу:

%hash_by_value = reverse %hash_by_key; # переворот списка $key = $hash_by_value{$value}; # поиск по бывшему значению

Нечетные элементы инвертированного списка становятся ключами, а четные - значениями хэша %hash_by_value.

Так как весь хэш, его ключи или значения можно легко преобразовать в список, то для обработки хэшей можно применять любые функции, работающие со списками. Именно поэтому в предыдущем примере была применена функция reverse. Например, вывести ключи и значения хэша на печать можно так:

{ # организовать блок, где объявить временный массив my @temp = %hash; # сохранить в нем хэш print "@temp"; # и передать его функции print } # по выходе из блока временный массив будет уничтожен

Можно напечатать хэш по-другому, построчно и в более облагороженном виде, при помощи функции map, которая также выполняет роль итератора:

print map {"Ключ: $_ значение: $hash{$_}\n" } keys %hash;

Перейти на страницу:

Похожие книги