Perl - 数组

时间:2016-12-30 01:32:09

标签: arrays perl filter

我正在尝试创建一个执行以下操作的子例程:

  1. 将两个数组作为输入(Filter,Base)
  2. 仅输出第一个
  3. 中不存在的第二个数组的值

    示例:

    @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 个答案:

答案 0 :(得分: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 :(得分: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;

请注意,集合是无序的,不能包含重复项。这可能是也可能不是你想要的。

答案 2 :(得分: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模块。