Почему не делает моего Perl grep, возвращают первое соответствие?

Шаблоны являются только инструментами и словарем. Вы пишете код, чтобы быть столь простыми, понятными и удобными в сопровождении, как Вы знаете как. Путем знания шаблонов у Вас есть больше альтернатив в Вашем распоряжении, и у Вас есть язык для обсуждения за и против подхода прежде, чем реализовать его.

В любом случае Вы только "переключаетесь" на "использование шаблона". Вы просто продолжаете делать то, что Вы всегда делаете, запишите код лучшим способом, Вы знаете как.

18
задан Brian Tompsett - 汤莱恩 1 June 2015 в 20:04
поделиться

6 ответов

Скобки изменяют контекст, в котором grep вычисляется, со скалярного контекста на контекст списка. В скалярном контексте grep возвращает количество раз, когда выражение было истинным. В контексте списка он возвращает элементы, для которых выражение было истинным.

Следующее подчеркивает разницу, которую имеет контекст:

my   $x   = grep {/foo/} @array;  # the number of things that match /foo/
my  ($x)  = grep {/foo/} @array;  # the first thing that matches /foo/
my  @foo  = grep {/foo/} @array;  # all the things that match /foo/
my (@foo) = grep {/foo/} @array;  # all the things that match /foo/
43
ответ дан 30 November 2019 в 05:54
поделиться

Скобки предоставляют контекст списка для grep . grep затем фактически вернет список элементов, для которых выражение было истинным, а не только количество раз, когда выражение было истинным.

8
ответ дан 30 November 2019 в 05:54
поделиться

grep функция ведет себя по-разному в контексте списка и скалярном контексте. Это задокументировано в perldoc -f grep :

Вычисляет BLOCK или EXPR для каждого элемента LIST (локально установка $ _ для каждого элемента) и возвращает значение списка состоящий из тех элементов, для которых вычислено выражение к истине. В скалярном контексте возвращает, сколько раз выражение было истинным.

Вы можете продублировать это самостоятельно с помощью плохо названной функции wantarray :

sub my_grep {
    my $sub = shift;
    my @return;
    for my $item (@_) {
        push @return if $sub->($item);
    }
    return @return if wantarray;
    return scalar @return;
}
5
ответ дан 30 November 2019 в 05:54
поделиться

grep возвращает список. Когда вы помещаете имя скалярной переменной в круглые скобки, Perl рассматривает все это l-значение как список, поэтому он присваивает этой переменной первое значение в списке.

Если бы у вас были другие скаляры в круглых скобках, вы бы получили второе, третье и т. д. значения из возвращаемого массива grep в них:

my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array;
1
ответ дан 30 November 2019 в 05:54
поделиться

Я думаю, вы ищете first_index из List :: MoreUtils :

use List::MoreUtils qw( first_index );

# ...

my $index = first_index { $_ eq $search_for } @array;
7
ответ дан 30 November 2019 в 05:54
поделиться

Кроме того, я думаю, что использование grep только для поиска первого экземпляра немного неэффективно, так как ему все равно нужно пройти и запустить обратный вызов для каждого элемента массива. Если ваш массив длинный, возможно, лучше написать цикл или использовать List :: MoreUtils, как указано выше.

1
ответ дан 30 November 2019 в 05:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: