2011-12-07 129 views
2

我想知道是否有任何簡單的算法來比較,看看一個哈希是否是另一個哈希的子集。perl,比較哈希,子集

例如,如果

$HASH{A} = B; 
$HASH{B} = C; 
$HASH{C} = D; 

$HASH2{A} = B; 
$HASH2{B} = C; 

然後%HASH2是%HASH的子集。

+0

您的意思是'$ HASH2的''而不是HASH1 $ {A}'{A}? –

+0

@MattFenwick:可能 - 我已經提前修好了。戈登,如果我錯了,請隨時恢復我的編輯。 – derobert

+0

感謝您的更正! – Gordon

回答

1

假設你的哈希值是簡單的(例如,它們不包含爲值引用),你可以用一個簡單的循環做到這一點:

sub is_subset { 
    my ($h1, $h2) = @_; 

    while (my ($k, $v) = each %$h1) { 
     exists $h2->{$k} && $v eq $h2->{$k} 
      or return; # in case of list context, thanks davorg 
    } 
    return 1; 
} 

在英語中,是經過在每個鍵,值對第一個散列,並問(a)是第二個散列中的關鍵字,(b)如果是,這些值是否相同?如果它發現一個不是,那麼第一個散列不是第二個散列的子集。否則,它是。

如果你的哈希值是比較複雜,例如,值可以是hashref,那麼你首先需要定義「子集」更好的(例如,是{ a => 1 }{ h2 => { a => 1 } }一個子集),並且可能使用一些遞歸(或檢查CPAN )。

+0

不錯!這是否也適用於數字? –

+0

@MattFenwick:好吧,如果你知道值是數字,我會把'eq'改成'=='。 – derobert

+0

@MattFenwick智能匹配運算符適用於字符串或整數'$ a ~~ $ b' – Axeman

4

它使用"smart matching"~~)和List::Util::first

use 5.010; 
use List::Util qw<first>; 

sub hash_is_subset { 
    my ($hash, $cand) = @_; 
    return not defined(first { not $hash->{ $_ } ~~ $cand->{ $_ } } keys %$cand); 
} 

hash_is_subset(\%HASH, \%HASH2); 
+0

之前從未聽說過智能匹配。感謝您的領導! –

+0

智能匹配可能導致驚喜。例如,「{a =>」hello「}是{a => qr /./}的子集?聰明的比賽說是的,我很確定。 – derobert