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

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

my @odd_numbers;
foreach (1..1000) {
push @odd_numbers, $_ if $_ % 2;
}

Для четного числа остаток от деления на 2 равен 0, а проверяемое условие ложно. Для нечетного числа остаток равен 1; значение истинно, поэтому в массив заносятся только нечетные числа. В этом коде нет ничего плохого, разве что он пишется и выполняется немного медленнее, чем следует, потому что в Perl имеется оператор grep:

my @odd_numbers = grep { $_ % 2 } 1..1000;

Этот фрагмент строит список из 500 нечетных чисел всего в одной строке кода. Как он работает? Первый аргумент grep содержит блок, в котором переменная $_ представляет текущий элемент списка. Блок возвращает логическое значение (true/false).


Остальные аргументы определяют список элементов, в котором выполняется поиск. Оператор grep вычисляет выражение для каждого элемента списка по аналогии с циклом foreach. Элементы, для которых последнее выражение в блоке возвращает истинное значение, включаются в итоговый список grep. Во время работы grep переменная $_ последовательно представляет один элемент списка за другим. Аналогичное поведение уже встречалось нам в цикле foreach. Как правило, изменять $_ в выражении grep не рекомендуется, потому что это приведет к повреждению исходных данных. Оператор grep унаследовал свое имя от классической утилиты UNIX, которая отбирает строки из файла по регулярным выражениям. Оператор Perl grep решает ту же задачу, но обладает гораздо большими возможностями. В следующем примере из файла извлекаются только те строки, в которых присутствует подстрока fred:

my @matching_lines = grep { /\bfred\b/i } ;

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

my @matching_lines = grep /\bfred\b/i, ;

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

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

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