为什么我的Perl grep没有返回第一场比赛?

时间:2009-08-11 19:47:18

标签: perl grep

以下代码段搜索数组中第一次出现值的索引。但是,当删除$ index周围的括号时,它无法正常运行。我做错了什么?

my ($index) = grep { $array[$_] eq $search_for } 0..$#array;

6 个答案:

答案 0 :(得分:42)

括号将从标量上下文评估grep的上下文更改为列表上下文。在标量上下文中,grep返回表达式为真的次数。在列表上下文中,它返回表达式为true的元素。

以下重点介绍了差异背景:

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/

答案 1 :(得分:8)

括号为list context提供grep。然后,grep将实际返回表达式为true的元素列表,而不仅仅是表达式为真的次数。

答案 2 :(得分:7)

我认为您正在寻找List::MoreUtils中的first_index

use List::MoreUtils qw( first_index );

# ...

my $index = first_index { $_ eq $search_for } @array;

答案 3 :(得分:5)

grep函数在列表上下文和标量上下文中的行为有所不同。这记录在perldoc -f grep

  

评估LIST的每个元素的BLOCK或EXPR(本地   将$ _设置为每个元素并返回列表值   由表达式评估的元素组成   为真。在标量上下文中,返回的次数   表达是真的。

您可以使用命名不佳的wantarray函数自行复制:

sub my_grep {
    my $sub = shift;
    my @return;
    for my $item (@_) {
        push @return if $sub->($item);
    }
    return @return if wantarray;
    return scalar @return;
}

答案 4 :(得分:1)

grep返回一个列表。当您将标量变量名称放在括号中时,Perl会将整个l值视为列表,因此它会将列表中的第一个值分配给该变量。

如果括号中有其他标量,你可以从grep的返回数组中得到第二个,第三个等值:

my ($index, $foo, $bar) = grep { $array[$_] eq $search_for } 0..$#array;

答案 5 :(得分:1)

另外,我认为使用grep只是为了找到第一个实例是有点低效的,因为它仍然需要遍历并在数组的每个元素上运行回调。特别是如果你的数组很长,你可能最好写一个循环,或者如上所述使用List :: MoreUtils。