以下代码段搜索数组中第一次出现值的索引。但是,当删除$ index周围的括号时,它无法正常运行。我做错了什么?
my ($index) = grep { $array[$_] eq $search_for } 0..$#array;
答案 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。