2011-02-03 60 views
16

當我嘗試以下方法如何從數組中減去數組?

#!/usr/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 

my @bl = qw(red green blue); 
my @a = qw(green yellow purple blue pink); 

print Dumper [grep {not @bl} @a]; 

我得到一個空數組。我預料@bl@a減去,所以輸出是yellow purple pink

這裏有什麼問題?

+2

「減」是不正確的字在這裏。當你**找到正確的單詞時,你會發現它是一個觸發巴洛克式散列攻擊的單詞。 – tchrist 2011-02-04 01:15:41

回答

33

您需要打開@bl到一個哈希執行差集:

my %in_bl = map {$_ => 1} @bl; 
my @diff = grep {not $in_bl{$_}} @a; 
+7

這比這個問題的常見問題回答更好 - 常見問題解答僅向您展示如何計算兩個數組之間的「對稱差異」 – mob 2011-02-03 21:35:33

+1

@mob:因此,郵件布萊恩與建議的更新。 – tchrist 2011-02-04 01:16:44

+6

在Perl 5.10或更新的版本中,您可以將其編寫爲`my @diff = grep {not $ _ ~~ @bl} @a;` – 2011-03-28 14:46:34

4

@b1計算結果爲真(這是一個非零數字元素的數組),因此布爾測試你的grep構造(not @b1)將始終返回false。 grep過濾僅返回布爾測試返回true的元素的數組。

您需要測試以確定$_(當前正在考慮的數組元素)是否在@bl之內。要做到這一點的方法之一是使用@bl作爲鍵,然後在grep的聲明支票的$_在哈希鍵的存在,產生一個臨時散:

#!/usr/bin/perl 

use strict; 
use warnings; 
use Data::Dumper; 

my @bl = qw(red green blue); 
my @a = qw(green yellow purple blue pink); 

# create a hash 
my %h; 

# nifty trick - use a hash slice to populate the 
# hash. The values are irrelevant so we'll use @bl 
# for those too 
@h{@bl} = @bl; 

print Dumper [grep {!exists $h{$_}} @a]; 
1

的另一種方法,使用minus功能從Acme::Tools CPAN模塊:

use strict; 
use warnings; 
use Data::Dumper; 
use Acme::Tools qw(minus); 

my @bl = qw(red green blue); 
my @a = qw(green yellow purple blue pink); 
my @diff = minus(\@a, \@bl); 
print Dumper(\@diff); 

__END__ 

$VAR1 = [ 
      'yellow', 
      'purple', 
      'pink' 
     ]; 
2

另一種選擇使用perl5i

use perl5i::2; 

my @bl = qw(red green blue); 
my @a = qw(green yellow purple blue pink); 
my @diff = @a->diff(\@bl); 

say @diff->mo->perl; 
4

由於Perl 5.18.0,smartmatch運算符被認爲是實驗性的: The smartmatch family of features are now experimental。 因此,我不會再使用下面的解決方案。

與Smartmatch運營商的另一種方式(如果你有Perl版本5.010或更高):

#!/usr/bin/env perl 
use warnings; 
use 5.012; 

my @bl = qw(red green blue); 
my @a = qw(green yellow purple blue pink); 

my @s = grep{ not $_ ~~ @bl } @a; 
say "@s"; # yellow purple pink 
-1

另一種方法是使用:

List::Compare CPAN module 
use List::Compare ; 
... 
my $compare_obj 
    = List::Compare->new(\@a , \@b1) ; 
@diff = $compare_obj->get_Lonly() ; 
...