Другая распространенная задача – преобразование элементов списка. Предположим, имеется список чисел, которые необходимо перевести в «денежный формат» для вывода, как в функции &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;