japhmi has asked for the wisdom of the Perl Monks concerning the following question:

I have 2 arrays, and I need to make sure all elements of array 1 are in array 2, but array 2 can have extra elements.

Examples:

OK:

@array1 = (a b c) @array2 = (a b c)

OK:

@array1 = (a b c) @array2 = (a b c d)

OK:

@array1 = (p d q) @array2 = (d p q)

NOT OK:

@array1 = (a b c e) @array2 = (a b c d)

The method that I've come up with so far is clunkey, with a copy of array2, and then 2 foreach loops, deleteing items from my copy - it's a mess and seems to like messing up. I'm looking for something more elegant.

Thank you monks!

Replies are listed 'Best First'.
Re: Compare arrays
by dorko (Prior) on May 28, 2010 at 18:48 UTC
    I do things like this all the time and I like to use List::Compare. It's worth a look.

    Cheers,

    Brent

    -- Yeah, I'm a Delt.
Re: Compare arrays
by kennethk (Abbot) on May 28, 2010 at 17:25 UTC
      Out of interest using your code as a base how do I print both of the array elements that have caused the mismatch ? e.g.
      array1 = "e" array2 = "d"
        There are a couple ways to interpret this question. I will assume you mean you would like the elements of each array that are excluded from the union of the two.

        #!/usr/bin/perl use strict; use warnings; my @array1 = qw(a b c e); my @array2 = qw(a b c d); my %hash; for my $key (@array2) { $hash{$key}++; } for my $key (@array1) { print "Fail #1: $key\n" unless $hash{$key}--; } for my $key (keys %hash) { print "Fail #2: $key\n" if $hash{$key} > 0; }

        For other related solutions, check out How do I compute the difference of two arrays? How do I compute the intersection of two arrays? in perlfaq4

Re: Compare arrays
by Argel (Prior) on May 28, 2010 at 21:29 UTC
    If you are using Perl 5.10 or later you can use the smart match operator (~~):
    use feature ":5.10"; use strict; use warnings; my @subset = qw(a b c e); my @superset = qw(b a c d x y z); my $missing = 0; foreach( @subset ) { $missing++ unless $_ ~~ @superset; } say "Number missing=$missing";

    Elda Taluta; Sarks Sark; Ark Arks

Re: Compare arrays
by Khen1950fx (Canon) on May 29, 2010 at 00:58 UTC
    At first I thought "intersection", but I remembered Re: Re: How do I compare two arrays? by Corion where Corion mentions symmetric difference between two sets. Take a look.

    Update: Here's another example Symmetric_difference

    #!/usr/bin/perl use strict; use warnings; my @a = qw( a b c ); my @b = qw( a b c d ); # Get the individual differences. my @a_minus_b = setminus(\@a, \@b); my @b_minus_a = setminus(\@b, \@a); # merge then together and remove possible duplicates my @symmetric_difference = uniq(@a_minus_b, @b_minus_a); # Present our results. print 'List A: ', join(', ', @a), "\nList B: ", join(', ', @b), "\nA \\ B: ", join(', ', @a_minus_b), "\nB \\ A: ", join(', ', @b_minus_a), "\nSymmetric difference: ", join(', ', @symmetric_difference), "\n"; # Takes two array references. Returns a list of elements in the first # array that aren't in the second. sub setminus { my ($a, $b) = @_; # Convert $b to hash keys, so it's easier to search. my %b; @b{@$b} = (); return grep !exists $b{$_}, @$a; } # take a list and return only uniq items sub uniq { my %saw; return grep !$saw{$_}++, @_; }
Re: Compare arrays
by kalyanrajsista (Scribe) on May 29, 2010 at 15:32 UTC
Re: Compare arrays
by baxy77bax (Deacon) on May 29, 2010 at 16:31 UTC
    hi,

    i must say, i'm not sure if you were looking for something like this but :

    #!/usr/bin/perl use strict; my @array_1 = qw(a b r gf s fg h j); my @array_2 = qw(g d s a b t z nbn df ert uz e ww); push (@array_2, grep{my $x = $_; not grep{$_ eq $x}@array_2}@array_1); print "@array_2\n";
    as the result you have an array_2 that has a unique set of all elements of array_2 plus those that are in array_1 and not in array two

    cheers