2010-03-28 78 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)。提交消息甚至會記錄對話!

相關問題