Функция each

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

while ( ($key, $value) = each %hash ) {
print "$key => $value\n";
}

В этом фрагменте происходит довольно много всего. Сначала each %hash возвращает пару «ключ-значение» из хеша в виде списка с двумя элементами; допустим, это ключ "c" со значением 3, а список имеет вид ("c", 3). Он присваивается списку ($key, $value), так что переменная $key содержит "c", а переменная $value содержит 3. Но это списочное присваивание выполняется в условном выражении цикла while, имеющем скалярный контекст. (А точнее логический контекст со значением true/false как конкретная разновидность скалярного контекста.) Значение списочного присваивания в скалярном контексте равно количеству элементов в исходном списке, то есть в данном случае 2.


Так как 2 интерпретируется как логическая истина, программа входит в тело цикла и выводит сообщение c = >3. При следующей итерации цикла each %hash дает новую пару «ключ-значение»; предположим, на этот раз была получена пара ("a", 1). (Функция each возвращает пару, отличную от предыдущей, потому что она отслеживает текущую позицию; говоря на техническом жаргоне, вместе с каждым хешем хранится итератор1.)

Эти два элемента сохраняются в ($key, $value). Количество элементов в исходном списке снова равно 2, то есть истинному значению; раз условие while истинно, тело цикла снова выполняется, и программа выводит a => 1. Мы снова входим в цикл. Теперь уже логика происходящего понятна, и вполне понятно, почему программа выводит сообщение b => 2. Но перебор не может продолжаться вечно. Когда Perl в следующий раз обрабатывает each %hash, пар «ключ-значение» больше не осталось, поэтому each возвращает пустой список. Пустой список присваивается ($key, $value), поэтому обеим переменным $key и $value присваивается undef. Но это не столь существенно, потому что все вычисления производятся в условном выражении цикла while. Значение списочного присваивания в скалярном контексте определяется как количество элементов в исходном списке; в данном случае оно равно 0.


Так как значение 0 интерпретируется как false, цикл while завершается, а выполнение продолжается в оставшейся части программы. Конечно, each возвращает пары «ключ-значение» в заранее неизвестном порядке. (Кстати, это тот же порядок, в котором возвращают результаты функции keys и values; «естественный» порядок хеша.) Если вам нужно перебрать элементы хеша в определенном порядке, отсортируйте ключи; это делается примерно так:

foreach $key (sort keys %hash) {
$value = $hash{$key};
print "$key => $value\n";
# Или без использования лишней переменной $value:
# print "$key => $hash{$key}\n";
}

Оцените статью: (0 голосов)
0 5 0

Статьи из раздела Perl на эту тему:
Зачем использовать хеш?
Интерполяция элементов хеша
Обращение к элементам хеша
Присваивание хешей
Типичные операции с хешами

Вернуться в раздел: Perl / 5. Хеши