in reply to comparing two arrays

I must say, in the nicest possible way, your question was a little terse. I can think of a lot of different situations you might have been interested in, many of which the above monks have dealt with. If, however, your situation was that you have an array like my @essentials = qw /1 3 5 7/; And you want to check an array @large to see whether @large contains at least all the contents of @essentials, then this wd be One Way To Do It:
my @essentials = qw /1 3 5 7/; my @large = qw /0 2 3 4 5 6 7 8/; my $result = "OK"; for my $i (@essentials) { unless (grep {$i == $_} @large) { $result = "NO"; last; } } print $result; # prints NO my @essentials = qw /1 3 5 7/; my @large = qw /0 1 2 3 4 5 6 7 8/; my $result = "OK"; for my $i (@essentials) { unless (grep {$i == $_} @large) { $result = "NO"; last; } } print $result; # prints OK
BUT... be careful with that == - you'll have to be careful to choose the right equality operator, depending on what's in your arrays.

§ George Sherston

Replies are listed 'Best First'.
Re: Re: comparing two arrays
by jdelmedi (Initiate) on Nov 24, 2001 at 19:42 UTC
    Thank you very much for your input, it has helped me to understand the methodology. I am quite new at this and can't seem to leave it alone unless I understand it. My question, if I may be a little more specific, I am dealing with a situation where I need to action something if for example a file with following contents; sqltable table loaded successfully with 282873 records. mike_test table loaded successfully with 282873 records. sarak_mike table loaded successfully with 282873 records. compares to a hard coded array @report=("sqltable", "mike_test ", "sarak_mike"); I need to check an array containing the file input @file to see whether @file contains at least all the contents of @report. Your help is greatly appreciated.
      No one has mentioned the Cookbook yet, so i will.

      If you need @file to contain at least all the elements of @report, then you need to find the simple difference of the two. The simple difference is the (paraphrasing from the Cookbook) "set of members of @report, but not of @file". If this set is empty, then @file contains at least all the elements of @report. So, working with Recipe 4.7:

      use strict; my @report = qw(sqltable mike_test sarak_mike); my @file = (@report, qw(plus a little more)); # off by 0 print '@file was off by ' . simple_compare(\@report,\@file) . " elements\n"; # still 0, that elem wasn't in @report pop @file; print '@file was off by ' . simple_compare(\@report,\@file) . " elements\n"; # off by 1, that one was shift @file; print '@file was off by ' . simple_compare(\@report,\@file) . " elements\n"; # returns number of elements in A that aren't in B sub simple_compare { my ($A,$B) = @_; # build lookup table my %seen = map { $_ => 1 } @$B; # find those in A that aren't in B my @aonly; foreach my $item (@$A) { push @aonly,$item unless ($seen{$item}); } return scalar @aonly; }
      (Array::Compare has a simple_compare() method, but it's definition of a simple compare is not the same as the Cookbook's.)

      Also note that this could only a be partial solution. What if you needed to compare these two arrays:

      my @report = qw(one one two); my @file = qw(one two two);
      Now what? @file definitely contains at least one of each element from @report. But, @file doesn't contain 2 'one's like @report does. If you need something like this, but you don't care about order, then use rob_au's suggestion and sort the arrays first. If you do care about order, use that code verbatim. Hope this helps!

      jeffa

      L-LL-L--L-LL-L--L-LL-L--
      -R--R-RR-R--R-RR-R--R-RR
      F--F--F--F--F--F--F--F--
      (the triplet paradiddle)
      
        Thanks for your help. I'm so close, but something is not working. I am trying to debug the following, but it seems that although both the @file contain the @report strings, I am not getting a match. Is it possible when I load the text file into @file array, that the elements are not compared as strings? Frusterating!!!!! The contents of the @file looks like this:
        sqltable_mike table loaded successfully with 282873
        sarak_mike table loaded successfully with 282873 records
        sticks table loaded successfully with 282873 records.
        hello table loaded successfully with 282873 records.
        All I need it to do is match all @report contents with the internal @file. What am I doing wrong. Your assistance is greatly appreciated. <CODE> use strict;
        my @compare=();
        my $file='d:\mms_tableload.txt';
        my @file="";
        open(FILE,"<$file");
        @file = <FILE>;
        close(FILE);
        my @report = qw(sqltable_mike sarak_mike );
        my @compare = ( @report, qw (@file ));
        # off by 0
        print '@file was off by '
        . simple_compare(\@report,\@compare)
        . " elements\n";
        # still 0, that elem wasn't in @report
        pop @file;
        print '@file was off by '
        . simple_compare(\@report,\@compare)
        . " elements\n";
        # off by 1, that one was
        shift @file;
        print '@file was off by '
        . simple_compare(\@report,\@file)
        . " elements\n";
        # returns number of elements in A that aren't in B
        sub simple_compare {
        my ($A,$B) = @_;
        # build lookup table
        my %seen = map { $_ => 1 } @$B;
        # find those in A that aren't in B
        my @aonly;
        foreach my $item (@$A) {
        push @aonly,$item unless ($seen{$item});
        }
        return scalar @aonly;
        }
        <CODE>