When I try the following
当我尝试以下
#!/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];
I get an empty array. I would have expected that @bl
was subtracted from @a
, so the output was yellow purple pink
.
我得到一个空数组。我原本预计会从@a中减去@bl,所以输出为黄紫色粉红色。
What's wrong here?
这有什么不对?
7 个解决方案
#1
33
You need to turn @bl
into a hash to perform the set difference:
您需要将@bl转换为哈希来执行设置差异:
my %in_bl = map {$_ => 1} @bl;
my @diff = grep {not $in_bl{$_}} @a;
#2
4
See perlfaq4: How do I compute the difference of two arrays?
请参阅perlfaq4:如何计算两个数组的差异?
In your code, not
is probably not doing what you think it is doing.
在你的代码中,可能没有做你认为它正在做的事情。
not @bl
will always be 1
if @bl
is an empty array, and undef
if @bl
is not empty. It doesn't mean "elements not in @bl
" in any sense.
如果@bl是空数组,则@bl将始终为1;如果@bl不为空,则不为@ff。在任何意义上,它并不意味着“不在@bl中的元素”。
#3
4
@b1
evaluates to true (it's an array with a non-zero number of elements), so the boolean test in your grep construct (not @b1
) will always return false. grep filters an array returning only the elements for which the boolean test returns true.
@ b1计算结果为true(它是一个元素数量非零的数组),因此grep结构中的布尔测试(不是@ b1)将始终返回false。 grep过滤一个数组,只返回布尔测试返回true的元素。
You need to test to see whether $_
(the array element currently under consideration) is in @bl
or not. One way to do this is to generate a temporary hash using @bl
as the keys, then in your grep statement check for the presence of $_
in the hash keys:
您需要测试$ _(当前正在考虑的数组元素)是否在@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];
#4
4
Since Perl 5.18.0 the smartmatch operator is considered experimental: The smartmatch family of features are now experimental. Because of that I wouldn't use this solution below any more.
自Perl 5.18.0以来,smartmatch运算符被认为是实验性的:smartmatch系列功能现在已经过实验。因此我不再使用此解决方案了。
Another way with the Smartmatch-operator ( if you have perl-version 5.010 or greater ):
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
#5
2
Another option using perl5i:
使用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;
#6
1
Another way, using the minus
function from the Acme::Tools CPAN module:
另一种方法,使用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'
];
#7
-1
Another way is to use:
另一种方法是使用:
List::Compare CPAN module
use List::Compare ;
...
my $compare_obj
= List::Compare->new(\@a , \@b1) ;
@diff = $compare_obj->get_Lonly() ;
...
#1
33
You need to turn @bl
into a hash to perform the set difference:
您需要将@bl转换为哈希来执行设置差异:
my %in_bl = map {$_ => 1} @bl;
my @diff = grep {not $in_bl{$_}} @a;
#2
4
See perlfaq4: How do I compute the difference of two arrays?
请参阅perlfaq4:如何计算两个数组的差异?
In your code, not
is probably not doing what you think it is doing.
在你的代码中,可能没有做你认为它正在做的事情。
not @bl
will always be 1
if @bl
is an empty array, and undef
if @bl
is not empty. It doesn't mean "elements not in @bl
" in any sense.
如果@bl是空数组,则@bl将始终为1;如果@bl不为空,则不为@ff。在任何意义上,它并不意味着“不在@bl中的元素”。
#3
4
@b1
evaluates to true (it's an array with a non-zero number of elements), so the boolean test in your grep construct (not @b1
) will always return false. grep filters an array returning only the elements for which the boolean test returns true.
@ b1计算结果为true(它是一个元素数量非零的数组),因此grep结构中的布尔测试(不是@ b1)将始终返回false。 grep过滤一个数组,只返回布尔测试返回true的元素。
You need to test to see whether $_
(the array element currently under consideration) is in @bl
or not. One way to do this is to generate a temporary hash using @bl
as the keys, then in your grep statement check for the presence of $_
in the hash keys:
您需要测试$ _(当前正在考虑的数组元素)是否在@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];
#4
4
Since Perl 5.18.0 the smartmatch operator is considered experimental: The smartmatch family of features are now experimental. Because of that I wouldn't use this solution below any more.
自Perl 5.18.0以来,smartmatch运算符被认为是实验性的:smartmatch系列功能现在已经过实验。因此我不再使用此解决方案了。
Another way with the Smartmatch-operator ( if you have perl-version 5.010 or greater ):
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
#5
2
Another option using perl5i:
使用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;
#6
1
Another way, using the minus
function from the Acme::Tools CPAN module:
另一种方法,使用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'
];
#7
-1
Another way is to use:
另一种方法是使用:
List::Compare CPAN module
use List::Compare ;
...
my $compare_obj
= List::Compare->new(\@a , \@b1) ;
@diff = $compare_obj->get_Lonly() ;
...