2011-03-03 48 views
18

我想知道Perl是否有內置的方法來檢查是否存在使用與特定正則表達式匹配的鍵的哈希元素。例如:Perl:將哈希鍵與正則表達式匹配

my %h = ('twelve' => 12, 'thirteen' => 13, 'fourteen' => 14); 

我想知道是否有什麼辦法可以做到這一點:

print "We have 12\n" if exists $h{twelve}; 
print "We have some teens\n" if exists $h{/.*teen$/}; 
+2

如果你有'teen $','。*'是多餘的。 – Axeman 2011-03-04 15:45:00

回答

24

smart match operator這樣做(從Perl v5.10開始可用)。

$a  $b  Type of Match Implied Matching Code 
====== =====  ===================== ============= 
... 
Regex Hash  hash key grep   grep /$a/, keys %$b 
... 

使用範例:

# print if any key in %h ends in "teen" 
print "We have some teens\n" if /.*teen$/ ~~ %h; 
+1

請注意,這個操作符一直處於不斷變化的狀態,並且從Perl 5.18開始就被視爲「實驗性」(在任何使用它的地方發出警告)。 http://stackoverflow.com/questions/16927024/perl-5-20-and-the-fate-of-smartmatch-and-given-when/ – sundar 2013-10-13 01:18:48

+1

這對我來說沒什麼問題。 – user1807271 2014-07-18 14:32:24

6

是的,這就是所謂的:

use List::Util qw<first>; 

# Your regex does not compile perhaps you mean /teen$/ 
my $value = $hash{ (first { m/teen/ } keys %hash) || '' }; 

(智能匹配之前,也就是見暴民對智能匹配的答案。)

你還可以對鍵進行分類:

my $value = $hash{ (first { m/teen/ } sort keys %hash) || '' }; 

我將凍結到這個 「操作」:

​​

而且你可以使用它像這樣:

my $key = values_for_keys_like(%hash => qr/teen/); 

或者

my $key = values_for_keys_like($base->{level_two}{level_three} => qr/teen/); 
+0

'sort'?嗯?如果您只是測試是否存在匹配,則沒有理由對鍵進行排序。只是'第一個{m/teen $ /}鍵%hash'比較好。 – 2011-03-04 11:44:42

+0

@Dave Sherohman:像往常一樣,這裏有一個普遍的問題,用戶正在尋找特定的應用程序。一般問題是「將散列鍵匹配到正則表達式」。 '第一個'是'任何'概念的實現 - 但包含其他含義:首先*如何?*我傾向於涵蓋更多的特定應用程序。 – Axeman 2011-03-04 15:47:57

+2

我無法看到任何排序適用於「有沒有匹配」的問題。是否存在匹配與訂單無關,因此訂單無關緊要。排序的唯一效果是強制執行特定的順序,但順序無關緊要,因此排序只是耗盡資源(時間/內存)而無用。這裏的問題是詢問關於「任何」的概念,與訂單無關;僅僅因爲'List :: Util'沒有提供'any'函數,'first'是合適的。 – 2011-03-05 11:08:33

12

除了其他的答案在這裏你也可以用perl的grep來做到這一點:

print "We have some teens\n" if grep {/.*teen/} keys %h;