Как мне найти, какие элементы в одном массиве не находятся в другом? - PullRequest
1 голос
/ 19 ноября 2009

Я новичок в программировании и, следовательно, застрял в проблеме базового уровня.

Ниже приведен код, который я написал для сравнения. Но результат, который я получаю, не имеет смысла для меня. Буду признателен, если кто-нибудь скажет мне, что происходит не так.

Существует два массива: @array1, @array2 неравной длины.

Я хочу сравнить оба и перечислить значения, отсутствующие в @ array1.

my %temp = map {$_,$_}@array2;
for (@array1){
next if exists $temp{$_};
open (FILE, ">>/filename") or die "$!";
print FILE "$_\n";
close(FILE);
}

Ответы [ 5 ]

10 голосов
/ 19 ноября 2009

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

Адаптируя код, который вы разместили:

#!/usr/bin/perl

use strict; use warnings;

my @x = 1 .. 10;
my @y = grep { $_ % 2 } @x;

my %lookup = map { $_ => undef } @y;

for my $x ( @x ) {
    next if exists $lookup{$x};
    print "$x\n";
}
5 голосов
/ 19 ноября 2009

Если вы делаете это для теста, который, как я полагаю, вам нужен, я бы настоятельно рекомендовал is_deeply в более новых версиях Test :: More

Вам придется обновить Test :: More

cpanp install Test::More

или если вы на Perl 5.5

cpan Test::More

Тогда тебе придется использовать это

use Test::More;
tests => 1
is_deeply ( \@arr1, \@arr2, 'test failed' );

Если вы не делаете это для тестирования, но делаете это для интроспективных целей и массивы небольшие, я бы предложил использовать XXX :

cpanp install http://search.cpan.org/CPAN/authors/id/I/IN/INGY/XXX-0.12.tar.gz

Тогда тебе придется его использовать

use XXX;
YYY [ \@arr1, \@arr2 ];
4 голосов
/ 19 ноября 2009

Это какой-то довольно умный код, который у вас есть. Ваш код более или менее идентичен тому, что написано в Perl FAQ. Однако у меня может возникнуть соблазн сделать это:

my %tmp  = map  { $_ => 1 } @array2;
my @diff = grep { not exists $tmp{$_} } @array1;

Это получает все в @array1, что не входит в @array2, но избегает всех этих зацикленных конструкций (стиль функционального программирования) Хотя то, что я бы действительно сделал бы так:

sub comp (\@\@) {
  my %t = map { $_ => 1 } @{$_[1]};
  return grep { not exists $t{$_} } @{$_[0]};
}

Тогда вы можете просто сделать:

my @diff = comp(@array1, @array2); # get items in @array1 not in @array2
@diff = comp(@arraty2, @array1); # vice versa

Или вы можете перейти на CPAN . List::Compare::Functional::complement() делает то, что вы хотите, хотя синтаксис обратный.

1 голос
/ 19 ноября 2009

Поменяйте @array1 и @array2 в вашем коде?

0 голосов
/ 01 октября 2015

Для простых значений, таких как строки или числа, должно работать следующее

my @result;
my $hosts = [qw(host1 host2 host3 host4 host5)];
my $stie_obj = [qw(host1 host5 host6)];

@result = map { my $a=$_; my $b=grep {/$a/} @$site_obj; $b==0 ? $a : () } @$hosts;
print Dumper (@result);

Должно дать:

$VAR1 = 'host2';
$VAR2 = 'host3';
$VAR3 = 'host4';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...