如何从数组中减去数组?

时间:2021-12-10 13:42:56

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() ;
...