2011-04-08 74 views
6

我一直在尋找一種方法來使用perl函數map: 給出一個哈希,我想提取對(鍵,值),其中值等於或匹配指定的參數。使用地圖來提取(密鑰,值)匹配指定值的哈希集

在我的示例中,我想提取(鍵,值)對,其中value = failed,但它也可以是表達式(即以A或REGEX開頭的字符串)。這就是爲什麼我想要一個散列,而不僅僅是一個匹配值的鍵。

my %strings = (
    bla => "success", 
    ble => "failed", 
    bli => "failed", 
    foo => "success", 
    blo => "failed", 
    bar => "failed", 
    blu => "success" 
); 

my %failed_s =(); 

while (my ($k, $v) = each %strings) { 
    if ($v eq 'failed') {$failed_s{$k} = $v}; 
}; 

我試着這樣做的幾種方法,但沒有很大的成績,所以我覺得我越來越感到困惑的引用,做作,結果等

my %failed_s = 
    map { { $_ => $strings{$_} } 
    if ($strings{$_}./failed/) } 
    keys %strings; 
my %failed_s = 
    map { ($strings{$_} eq 'failed') && 
      ($_, $strings{$_}) } 
    keys %strings; 

print "Dumper \%failed_s: \n" . Dumper(\%failed_s); 

這可能是不可能或不在這種情況下有效地使用地圖,但它會幫助我(也可能是其他人)知道爲什麼。

+0

我會使用perl的'grep' – knittl 2011-04-08 15:48:01

+0

@knittl我也試過,但不知道如何使它工作eather,如果你有一個例子或想法,我會很高興看到它! – Thomas 2011-04-08 16:15:47

+1

查看@ mob的[answer](http://stackoverflow.com/questions/5597542/using-map-to-extract-hash-set-of-key-value-matching-specified-value/5597656#5597656)。 – 2011-04-08 16:27:12

回答

6

在您的第一個地圖示例中,您返回的是單個元素哈希引用,這不是您想要的。

在第二個問題中,&&運算符在其參數上施加了標量上下文,因此列表($_, $strings{$_})僅返回列表中的最後一個項目。

你所尋找的是:

my %failed_s = map { 
    $strings{$_} eq 'failed' ? ($_, $strings{$_}) :() 
} keys %strings; 

? :操作如果條件爲true,則返回列表,以及一個空列表,如果它是假的。

+0

空列表是防止地圖將自身傳遞給%失敗的地方,這會拋出數據。 – 2011-04-08 16:13:22

3

map FUNC, LIST對列表中的每個元素進行操作。你的函數可能會返回一些空元素的列表(如Eric Strom的答案所示)。另一種方法是使用另一種過濾器,以便map只在你感興趣的內容進行操作:

my %failed_s = map { 
    $_ => $strings{$_} 
} grep { $strings{$_} eq 'failed' } keys %strings; 
8

Perl已經度過了一個輕鬆訪問哈希邏輯到這樣的程度,很少人已經能夠區分關鍵從最常見的實現中選擇價值對概念:哈希。

所以當大多數貝勒斯想到KVP時,他們會認爲是「哈希」。但想想Perl數組的方式是1)列表,2)隊列,3)堆棧,你會看到實現不完全等於概念。

我認爲有必要以一種方式來治療哈希之外,所以我創建了自己的圖書館,我的意思是上傳到CPAN,直到我發現List::Pairwise已經存在。

(似乎當然它不會有我的「散列拼接」的方法...)

總之,使用List::Pairwise,你只需

use List::Pairwise qw<grepp>; 
my %failed_s = grepp { $b eq 'failed' } %strings; 

我覺得自己像電視購物節目的傢伙時,我說:「看看這簡直太簡潔了!」

3

我認爲map + grep組合更乾淨。

my %failed_s = 
    map { $_ => $strings{$_} } 
    grep { $strings{$_} eq 'failed' } 
    keys(%strings); 

但由於grep的可利用地圖來實現,

my %failed_s = 
    map { $_ => $strings{$_} } 
    map { $strings{$_} eq 'failed' ? $_ :() } 
    keys(%strings); 

它可以只用地圖來完成。

my %failed_s = 
    map { $strings{$_} eq 'failed' ? ($_ => $strings{$_}) :() } 
    keys(%strings); 

他們遇到的問題是,當您打算什麼都不返回時,您返回false。

+0

謝謝,這說得很清楚! – Thomas 2011-04-11 10:30:30

相關問題