Как вычесть массив из массива? - PullRequest
17 голосов
/ 04 февраля 2011

Когда я попробую следующее

#!/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.

Что здесь не так?

Ответы [ 7 ]

34 голосов
/ 04 февраля 2011

Вам нужно превратить @bl в хеш для выполнения заданной разницы:

my %in_bl = map {$_ => 1} @bl;
my @diff  = grep {not $in_bl{$_}} @a;
4 голосов
/ 04 февраля 2011

Начиная с Perl 5.18.0, оператор smartmatch считается экспериментальным: Семейство функций smartmatch теперь является экспериментальным .Из-за этого я больше не буду использовать это решение ниже.

Другой способ с Smartmatch-оператором (если у вас версия perl 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 голосов
/ 04 февраля 2011

@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];
4 голосов
/ 04 февраля 2011

См. perlfaq4: Как вычислить разницу двух массивов?

В вашем коде not, вероятно, не выполняет то, что вы думаете.

not @bl всегда будет 1, если @bl - пустой массив, и undef, если @bl - не пустой.Это ни в коем случае не означает «элементы не в @bl».

2 голосов
/ 04 февраля 2011

Другая опция, использующая 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;
1 голос
/ 04 февраля 2011

Другой способ, используя функцию minus из модуля 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'
        ];
0 голосов
/ 17 апреля 2015

Другой способ заключается в использовании:

List::Compare CPAN module
use List::Compare ;
...
my $compare_obj 
  = List::Compare->new(\@a , \@b1) ;
@diff = $compare_obj->get_Lonly() ;
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...