Ответ 1
Вам нужно превратить @bl
в хеш для выполнения заданной разницы:
my %in_bl = map {$_ => 1} @bl;
my @diff = grep {not $in_bl{$_}} @a;
Когда я попробую следующее
#!/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
.
Что здесь не так?
Вам нужно превратить @bl
в хеш для выполнения заданной разницы:
my %in_bl = map {$_ => 1} @bl;
my @diff = grep {not $in_bl{$_}} @a;
См. perlfaq4: Как вычислить разницу в двух массивах?
В вашем коде not
, вероятно, не делает то, что, по вашему мнению, делает.
not @bl
всегда будет 1
, если @bl
- пустой массив, а undef
, если @bl
не пуст.
Это не означает "элементы не в @bl
" в любом смысле.
@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];
Поскольку 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
Другая опция, использующая 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;
Другой способ, используя функцию 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'
];
Другой способ:
List::Compare CPAN module
use List::Compare ;
...
my $compare_obj
= List::Compare->new(\@a , \@b1) ;
@diff = $compare_obj->get_Lonly() ;
...