2016-12-30 50 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模块。