Преобразование элементов списка

Другая распространенная задача – преобразование элементов списка. Предположим, имеется список чисел, которые необходимо перевести в «денежный формат» для вывода, как в функции &big_money. Однако исходные данные изменяться не должны; нам нужна измененная копия списка, используемая только для вывода. Одно из возможных решений:

my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95);
my @formatted_data;
foreach (@data) {
push @formatted_data, &big_money($_);
}

Немного напоминает пример кода, приведенный в начале описания grep, не правда ли? Вероятно, вас не удивит, что альтернативное решение напоминает первый пример с grep:

my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95);
my @formatted_data = map { &big_money($_) } @data;

Оператор map похож на grep, потому что он получает те же аргументы: блок, в котором используется $_, и список элементов для обработки. И функционирует он сходным образом: блок последовательно выполняется для каждого элемента списка, а $_ при каждой итерации представляет новый элемент списка. Но последнее выражение блока для map используется иначе: вместо логического признака оно определяет значение, включаемое в итоговый список.


Любую конструкцию с grep или map можно переписать в виде эквивалентного цикла foreach с занесением элементов во временный массив, но короткая запись обычно и эффективнее, и удобнее. Результат map и grep представляет собой список, что позволяет напрямую передать его другой функции. В следующем примере отформатированные «денежные величины» выводятся в виде списка с отступами под заголовком:

print "The money numbers are:\n",
map { sprintf("%25s\n", $_) } @formatted_data;

Конечно, всю обработку можно выполнить «на месте» без использования временного массива @formatted_data:

my @data = (4.75, 1.5, 2, 1234, 6.9456, 12345678.9, 29.95);
print "The money numbers are:\n",
map { sprintf("%25s\n", &big_money($_) ) } @data;

У map, как и у grep, существует упрощенная форма синтаксиса. Если в качестве селектора используется простое выражение (вместо полноценного блока), поставьте это выражение, за которым следует запятая, на место блока:

print "Some powers of two are:\n",
map "\t" . ( 2 ** $_ ) . "\n", 0..15;

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

Статьи из раздела Perl на эту тему:
Отбор элементов списка
Перехват ошибок в блоках eval
Срезы
Срезы массивов
Срезы хешей

Вернуться в раздел: Perl / 16. Расширенные возможности Perl