2010-03-28 63 views
10

我有一个数据结构是一个包含散列数组的散列。我想到达那里,并拿出第一个匹配我正在寻找的值的散列。我尝试这样做:为什么Perl的移位抱怨'参数1的类型必须是数组(不是grep迭代器)。'?

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

但是,这给了我这个错误:Type of arg 1 to shift must be array (not grep iterator).我重读perldocgrep,我觉得我在做什么是有意义的。 grep返回一个列表,对吧?它是否在错误的环境中?

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

回答

18

A list isn't an array

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

...应该做的工作。从列表上下文中的grep返回,但不要分配除第一个以外的任何值。

+5

我想我会写白名单上的'列表不是数组'100次。谢谢。 – wes 2010-03-28 22:19:57

+0

现在有一个更好的答案为这个常见问题解答:http://www.effectiveperlprogramming.com/blog/39 – 2010-03-28 22:31:18

+0

@brian d foy - 何时常见问题得到更新? (即,我们会在Perl 5版本10的发行版中看到它,还是会在版本12中发布?) – Quentin 2010-03-28 22:37:56

17

我认为更好的方式来写,这将是这样的:

use List::Util qw/first/; 

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

它不仅将更加清楚你正在试图做的,这也将是更快,因为它会阻止你的grepping什么阵一旦找到匹配的元素。

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列表文件的下标:

A list value may also be subscripted like a normal array. You must put the list in parentheses to avoid ambiguity. For example:

# 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那天是修补机器 - 当天晚上实现了它。

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

相关问题