2010-06-15 53 views
7

讓我們說在Perl中我有一個哈希引用列表,每個都需要包含某個字段,比如說foo。我想創建一個包含foo的所有映射的列表。如果存在不包含foo的散列,則該過程將失敗。Perl,獲取所有散列值

@hash_list = (
{foo=>1}, 
{foo=>2} 
); 

my @list =(); 
foreach my $item (@hash_list) { 
    push(@list,$item->{foo}); 
} 

#list should be (1,2); 

在Perl中有更簡潔的方法嗎?

+1

我只是想澄清你沒有創建一個映射列表,你正在創建一個包含每個hashes'foo'值的列表,而你的代碼示例與'process failing'無關,所以你不只是要求更簡潔。 – 2010-06-15 20:25:04

+1

一般來說:每當你發現自己正在做'foreach ... {... push ..}'你可以使用map或grep使代碼變得更簡單和簡單。 – Ether 2010-06-15 20:32:22

回答

6

是的。有。

my @list = map { 
    exists $_->{foo} ? $_->{foo} : die 'hashed lacked foo' 
    } 
    @hash_list 
; 
+0

對於像這樣的複雜地圖表達式,通常使用塊語法更容易閱讀,而不是使用裸表達式 – 2010-06-15 21:31:22

+0

,這是更好的+1,我一直使用簡單表達式的裸語法,可能是唯一沒有得到一個塊是一個映射的情況下,返回一個arrayref:'map [...] => ...' – 2010-06-15 23:37:44

0
if (@hash_list != grep { exists $_->{foo} } @hash_list) { 
    # test failed 
} 
1

埃文的回答是接近,但將返回hashrefs而不是foo的值。

my @list = map $_->{foo} grep { exists $_->{foo} } @hash_list 
+0

是的,我解決了這個問題。而且,我也讓它死亡,他的代碼和他的問題之間存在脫節。你也可以用一個循環做到這一點。 – 2010-06-15 20:28:12

2

您可以使用地圖功能是:

@hash_list = (
{foo=>1}, 
{foo=>2} 
); 

@list = map($_->{foo}, @hash_list); 

在地圖上的第二個參數的所有元素的第一個參數應用功能。

grep也很酷,可以過濾列表中的元素,並以相同的方式工作。