为什么Perl的转变抱怨'转移的类型1必须是数组(不是grep iterator)。'?

时间:2010-03-28 22:05:06

标签: perl syntax grep

我有一个数据结构,它是一个包含哈希数组的哈希。我想到达那里并拿出与我正在寻找的值相匹配的第一个哈希值。我试过这个:

   my $result = shift grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};

但是这给了我这个错误:Type of arg 1 to shift must be array (not grep iterator).我重新阅读了grep的{​​{3}},我认为我正在做的事情是有道理的。 grep会返回一个列表,对吗?它是在错误的背景下吗?

我现在会使用临时变量,但我想弄清楚为什么这不起作用。

3 个答案:

答案 0 :(得分:18)

A list isn't an array

my ($result) = grep {$_->{name} eq 'foo'} @{$hash_ref->{list}};

......应该做好这份工作。从列表上下文中的grep返回,但不要指定除第一个之外的任何值。

答案 1 :(得分:17)

我认为更好的方法是写这个:

use List::Util qw/first/;

my $result = first { $_->{name} eq 'foo' } @{ $hash_ref->{list} };

不仅会更清楚你要做什么,它也会更快,因为一旦找到匹配的元素,它将停止grepping你的数组。

答案 2 :(得分:2)

另一种方法:

my $result = (grep {$_->{name} eq 'foo'} @{$hash_ref->{list}})[0];

请注意,grep的第一个参数周围的曲线在这种情况下是多余的,因此您可以使用

来避免块设置和拆卸成本
my $result = (grep $_->{name} eq 'foo', @{$hash_ref->{list}})[0];

“List value constructors” in perldata文件下载列表:

  

列表值也可以像普通数组一样下标。您必须将列表放在括号中以避免歧义。例如:

# Stat returns list value.
$time = (stat($file))[8];

# SYNTAX ERROR HERE.
$time = stat($file)[8];  # OOPS, FORGOT PARENTHESES

# Find a hex digit.
$hexdigit = ('a','b','c','d','e','f')[$digit-10];

# A "reverse comma operator".
return (pop(@foo),pop(@foo))[0];

我记得,当Randal Schwartz开玩笑地提出这个问题时我们得到了这个功能,Chip Salzenberg - 当时是一个修补机器 - 那天晚上实现了它。 < / p>

更新:一些搜索显示我想到的功能是$coderef->(@args)。提交消息甚至会记录对话!