2010-04-15 74 views
7

我不明白從Programming Perl 3e這個功能的最後一行。這個Perl grep如何確定幾個哈希的聯合?

這裏是你會如何編寫通過返回傳遞給它的所有哈希值發生鍵的列表確實是一種交集的功能:

@common = inter(\%foo, \%bar, \%joe); 
sub inter { 
    my %seen; 
    for my $href (@_) { 
     while (my $k = each %$href) { 
      $seen{$k}++; 
     } 
    } 
return grep { $seen{$_} == @_ } keys %seen; 
}

我明白%seen是一個哈希這將每個鍵映射到在提供給該函數的任何散列中遇到的次數。

回答

16

grep將傳遞給它的列表(在這種情況下,在任何hashrefs中看到的每個元素);並返回僅包含塊中表達式爲真的元素的列表(本地將$_變量設置爲列表中的每個元素)。

讓我們看看這個表情是如何計算:

  • @_是傳遞給子程序的所有參數的陣列 - 在我們的情況下,通過哈希引用列表

  • 在。 $seen{$_} == @_表達式該列表被強制爲scalar context(由於==)。

  • 當在標量上下文中使用的,表的計算結果爲列表中的元素的數量 - 在上面的示例呼叫,到3中,由於3個hashrefs被傳入

因此,對於%seen中的每個密鑰(例如,在N個hashrefs中的任一個中看到的每個密鑰);表達式$seen{$_} == @_在數值上比較了哈希中元素被看到的次數與哈希總數 - 它只會相等,當然,如果元素在所有傳入的哈希中,並且因此是我們想要的交集的成員。

因此,爲了總結分析,grep將返回發生在每一個散列(也就是發生N次,其中N是散列數)中的所有鍵的列表。例如。交叉點。

+0

我喜歡這個最近編輯的鍵從%seen鍵。很好的答案,DVK。 – spazm 2010-04-15 05:41:04

+0

非常好。保存了我的一天。我實際上編寫了一段代碼來理解正在發生的事情,並將我的頭撞到了將近一個小時,但無法弄清楚。 – anukalp 2014-11-16 12:25:01

2

該函數的用途是查找傳遞給它的所有散列中出現的元素。

最後一行grepkeys %seen返回的列表。要確定給定的鍵是否出現在所有傳遞給該函數的散列中,我們可以將該鍵的值%seen與參數inter的值進行比較。

grep塊中,將$_設置爲keys列表的每個元素,並對某些條件進行測試。

標量上下文中的數組計算爲其長度。 @_是傳遞給子例程的參數數組。 ==運算符將其操作數置於標量上下文中,因此我們可以將$seen{$_}的值與@_的長度進行比較。如果它們是相同的,那麼這個關鍵就出現在所有的哈希中。

3
grep block list 

這將依次將塊應用到列表的每個元素,該元素被別名爲$ _。如果該塊返回true,則將該元素添加到返回的數組中。

在這種情況下

grep { $seen{$_} == @_ } keys %seen 

塊是$seen{$_} == @_,這對進行比較的@_看到散列的值。 @_在標量上下文中進行評估,因此返回@_數組中元素的數量。 @_代表當前函數的參數。在這種情況下,(\%foo, \%bar, \%joe)在標量上下文中返回3。我們的清單是keys %seen,它是一個包含%seen中存在的所有密鑰的數組。

相當於英文陳述:

  • 「給我所有鍵的列表,從 %seen其中具有 關聯的值是關鍵等於傳遞給這個函數 元素的數量」
  • 「給我一個從 %seen的所有鍵的列表,其中與 關鍵的值是3
  • 「給我一個列表 個所有具有 值3,即所有來自%seen 存在於每個3個 hashrefs傳遞給這個函數」