How do I find which elements in one array aren't in another?
I am new to programming and hence I am stuck on a basic level problem.
Following is code I wrote for comparison. But the result I get does not make sense to me. I would appreciate if someone could tell me what is going wrong.
There are two arrays: @array1
, @array2
of unequal length.
I wish to compare both and list down values not present in @array1.
my %temp = map {$_,$_}@array2;
for 开发者_StackOverflow(@array1){
next if exists $temp{$_};
open (FILE, ">>/filename") or die "$!";
print FILE "$_\n";
close(FILE);
}
See the FAQ How do I compute the difference of two arrays? How do I compute the intersection of two arrays?
Adapting the code you posted:
#!/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";
}
If you're doing this for a test, which I assume you are I would highly suggest is_deeply in the newer versions of Test::More
You'll have to update Test::More
cpanp install Test::More
or if you're on perl 5.5
cpan Test::More
Then you'll have use it
use Test::More;
tests => 1
is_deeply ( \@arr1, \@arr2, 'test failed' );
If you're not doing this for testing, but you're doing this for introspective purposes and the arrays are small, I'd suggest using XXX:
cpanp install http://search.cpan.org/CPAN/authors/id/I/IN/INGY/XXX-0.12.tar.gz
Then you'll have use it
use XXX;
YYY [ \@arr1, \@arr2 ];
That's some pretty clever code you've got there. Your code is more or less identical to what the Perl FAQ says. I might be tempted to do this, however:
my %tmp = map { $_ => 1 } @array2;
my @diff = grep { not exists $tmp{$_} } @array1;
This gets everything in @array1
that's not in @array2
, but avoiding all of those out-of-style looping constructs (yay for functional programming). Though what I'd really do is this:
sub comp (\@\@) {
my %t = map { $_ => 1 } @{$_[1]};
return grep { not exists $t{$_} } @{$_[0]};
}
Then you can just do:
my @diff = comp(@array1, @array2); # get items in @array1 not in @array2
@diff = comp(@arraty2, @array1); # vice versa
Or you can go to CPAN. List::Compare::Functional::complement()
does what you want, though the syntax is reversed.
Swap @array1
and @array2
in your code?
For simple values like strings or numbers, the following should work
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);
Should give :
$VAR1 = 'host2';
$VAR2 = 'host3';
$VAR3 = 'host4';
精彩评论