2016-12-30 38 views
1

我試圖創建一個子程序,它執行以下濾波函數:的Perl - 用於數組

  1. 採用兩個數組作爲輸入(過濾器,基峯)
  2. 僅輸出該做第二陣列的值

    @a = (1, 2, 3, 4, 5); 
    @b = (1, 2, 3, 4, 5, 6, 7); 
    
    Expected output : @c = (6, 7); 
    Called as : filter_list(@filter, @base) 
    
    ############################################### 
    
    sub filter_list { 
        my @names = shift; 
        my @arrayout; 
        foreach my $element (@_) 
        { 
         if (!($element ~~ @names)){ 
         push @arrayout, $element; 
        } 
        } 
        return @arrayout 
    } 
    

    測試運行:在第一

實施例不存在

@filter = ('Tom', 'John'); 
@array = ('Tom', 'John', 'Mary'); 
@array3 = filter_list(@filter,@array); 
print @array3; 
print "\n"; 

結果:

JohnJohnMary 

誰能幫助?謝謝。

+3

([兩個陣列使用Perl的不同]的可能的複製http://stackoverflow.com/questions/2933347/差的兩陣列,使用-perl的) – ThisSuitIsBlackNot

回答

5

您不能將數組傳遞給subs,只有標量。所以,當你做

my @filtered = filter_list(@filter, @base); 

你真的做

my @filtered = filter_list($filter[0], $filter[1], ..., $base[0], $base[1], ...); 

因此,當你做

my @names = shift; 

你真的做

my @names = $filter[0]; 

這顯然是錯誤。

最簡單的解決方案是將引用傳遞給數組。

my @filtered = filter_list(\@filter, \@base); 

散列允許有效實現(O(N + M))。

sub filter_list { 
    my ($filter, $base) = @_; 
    my %filter = map { $_ => 1 } @$filter; 
    return grep { !$filter{$_} } @$base; 
} 

或者,

my @filtered = filter_list(\@filter, @base); 

可以被實現爲

sub filter_list { 
    my $filter = shift; 
    my %filter = map { $_ => 1 } @$filter; 
    return grep { !$filter{$_} } @_; 
} 
1

你在找什麼是兩套的差異。這與工會,十字路口以及其他許多人一起是set operations。而不是寫自己的,有很多modules for dealing with sets

Set::Object是非常快速和有特點的。我會避免使用操作員界面(即$ set1 - $ set2),因爲它會使代碼混淆。而是使用顯式的方法調用。

use strict; 
use warnings; 
use v5.10; 

use Set::Object qw(set); 

my $set1 = set(1, 2, 3, 4, 5); 
my $set2 = set(1, 2, 3, 4, 5, 6, 7); 
say join ", ", $set2->difference($set1)->members; 

請注意,集合是無序的,不能包含重複項。這可能是也可能不是你想要的。

1

這使用List::Compare,這是一個具有大量例程比較列表的模塊。

在這裏,你想get_complement

use warnings; 
use strict; 

use List::Compare; 

my @arr1 = (1, 2, 3, 4, 5); 
my @arr2 = (1, 2, 3, 4, 5, 6, 7); 

my $lc = List::Compare->new(\@arr1, \@arr2); 

my @only_in_second = $lc->get_complement; 

print "@only_in_second\n"; 

該模塊有很多選擇。

如果您不需要排序的結果,請將-u傳遞給構造函數以獲得更快的操作。

還有「加速模式」,通過傳遞-a獲得。爲了在相同陣列之間高效地重複比較,許多事情在施工時被預先計算。有了這個被抑制的標誌,這加快了單個比較。請參閱List::Compare Modes

這兩個選項可以合併,List::Compare->new('-u', '-a', \@a1, \@a2)

支持三個或更多列表上的操作。

還有功能接口,作爲單獨的List::Compare::Functional模塊。