当我尝试以下
时#!/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
。
这里有什么问题?
答案 0 :(得分:34)
您需要将@bl
转换为哈希来执行设置差异:
my %in_bl = map {$_ => 1} @bl;
my @diff = grep {not $in_bl{$_}} @a;
答案 1 :(得分:4)
请参阅perlfaq4: How do I compute the difference of two arrays?
在您的代码中,not
可能没有按照您的想法进行操作。
not @bl
为空数组,则{p> 1
始终为@bl
;如果undef
不为空,则@bl
将为@bl
。
它并不意味着“任何意义上都不在{{1}}中的元素”。
答案 2 :(得分:4)
@b1
求值为true(它是一个元素数量非零的数组),因此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];
答案 3 :(得分:4)
自Perl 5.18.0起,smartmatch运算符被认为是实验性的: The smartmatch family of features are now experimental。 因此我不再使用此解决方案了。
使用Smartmatch-operator的另一种方法(如果你有perl-version 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
答案 4 :(得分: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;
答案 5 :(得分:1)
另一种方法,使用Acme::Tools CPAN模块中的minus
函数:
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'
];
答案 6 :(得分:-1)
另一种方法是使用:
List::Compare CPAN module
use List::Compare ;
...
my $compare_obj
= List::Compare->new(\@a , \@b1) ;
@diff = $compare_obj->get_Lonly() ;
...