Beefy Boxes and Bandwidth Generously Provided by pair Networks
Do you know where your variables are?
 
PerlMonks  

Comparing arrays

by hotshot (Prior)
on Dec 24, 2002 at 08:28 UTC ( [id://222071]=perlquestion: print w/replies, xml ) Need Help??

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

Morning All !

What is the fastest/shortest way to compare two arrays (without using any special modules)?.
I need to know only if they are different, I don't need to know what is the difference itself.

Thanks

Hotshot

Replies are listed 'Best First'.
Re: Comparing arrays
by jsprat (Curate) on Dec 24, 2002 at 08:59 UTC
    From perlfaq4:

    $are_equal = compare_arrays(\@frogs, \@toads); sub compare_arrays { my ($first, $second) = @_; no warnings; # silence spurious -w undef complaints return 0 unless @$first == @$second; for (my $i = 0; $i < @$first; $i++) { return 0 if $first->[$i] ne $second->[$i]; } return 1; }

    Note that compare_arrays returns as soon as it can determine the equality - immediately if the refs point at the same array. If not, it returns as soon as it finds the first difference.

    Update: Misread it as $first == $second zigdon is correct

      Don't you mean that it returns as soon as it can determine the arrays are different? Immediately if the arrays are not of the same length!

      -- Dan

Re: Comparing arrays
by cchampion (Curate) on Dec 24, 2002 at 14:00 UTC
    have a look at a previous comparing arrays here in Perlmonks.
    There are examples, links to similar solutions, and benchmarks of different methods, so that you may choose the one you are more conmfortable with.

    Merry Christmas

    cchampion
Re: Comparing arrays
by BrowserUk (Patriarch) on Dec 24, 2002 at 09:15 UTC

    Update: In deference to Arien's concerns.

    if ( do{ local$"=''; @array1 == @array2 and "@array1" eq "@array2"} ) +{ print 'They are the same', $/; }

    Which of course will also break if you have two arrays,

    my @a = ( 'onetwo','', 'three'); my @b = ( 'one', 'two', 'three' );

    And as with any shortcuts, you need to know your data before you apply them. If your not comforable with that, don't use it.

    Update more:

    I'll spell it out for those unable or unwilling to make the mental leap for themselves.

    If your data is wholey numeric, then use $"=<any non-numeric-char>.

    If your data consists of wholey alpha data use a non-alpha char.

    If your data consists of mixed alpha-numeric then use a non-alpha-numeric.

    If your data can contain any char in the range 32-127, cosider using a control character (eg."\cA").

    If your data can contain any 7-bit char, use an 8-bit char. 128-255.

    If there is simply no character that your data does not contain, then you need to compare element-by-element. These cases are very rare. In almost all normal sets of data it is possible to find a single char that you can get away with using, and eq testing of the stringyfied arrays is a simple, and efficient way of performing this kind of test on small datasets.

      That doesn't necessarily work as intended if the values of one or more elements in either array contain the list separator $":

      my @array1 = qw(one two three); my @array2 = ("one" . $" . "two", "three"); if ("@array1" eq "@array2") { print 'They are the same', $/; # no, they are NOT }

      The updated code is still flawed, consider:

      my @array1 = qw(one two three); my @array2 = qw(onetwo three); if ( do{ local $" = ''; "@array1" eq "@array2"} ) { print 'They are the same', $/; # no, they are NOT }

      This second update still isn't the way to do it... I took out the local $" (which should be no problem as the value of $" shouldn't matter anyway). Consider:

      my @array1 = ("one", "two" . $" . "three"); my @array2 = ("one" . $" . "two", "three"); if ( do{ @array1 == @array2 and "@array1" eq "@array2"} ) { print 'They are the same', $/; # no, they are NOT }

      Stringifying would only work if it is guaranteed that $" doesn't occur as a substring of one or more values of either array.

      — Arien

Re: Comparing arrays
by Ryszard (Priest) on Dec 24, 2002 at 13:09 UTC
    sort the array, join it with a null, then do a compare.
    my $ary1 = join(/\0/, sort(@array1)); my $ary2 = join(/\0/, sort(@array2)); if ($ary1 eq $ary2) {....}

      But of course if you do a sort first then you loose the position of the elements in the array. If the position of the elements is not significant, this is a good solution.

      CountZero

      "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Comparing arrays
by vek (Prior) on Dec 24, 2002 at 13:26 UTC
    Just out of curiosity hotshot, why don't you want to use modules? The only reason I'm asking is that you'll be missing out on davorg's Array::Compare which is a shame really.

    -- vek --
Re: Comparing arrays
by pg (Canon) on Dec 25, 2002 at 01:00 UTC
    The shortest, but far from the fastest:
    use Data::Dumper; ... (Dumper(@a) eq Dumper(@b))?print "same":print "different";
    If your arrays are not big, this is actually not a bad solution, and it is handy, but don't use it when the arrays are big :-)(I assume that you care the sequence of elements)
Re: Comparing arrays
by bart (Canon) on Dec 25, 2002 at 11:21 UTC
    sub array_eq { my($ar1, $ar2) = @_; @$ar1 == @$ar2 or return 0; return !grep { $ar1->[$_] ne $ar2->[$_] } 0 .. $#$ar1; } print array_eq (['one', 'two', 'three'], ['three', 'one', 'two']) ? + 'the same' : 'different';
    with the usual caveats... No nested structures, for example. If you're in that case, I too would try freezing the arrays, but with Storable, and compare the strings. (In case there could be hashes in there, check out the section entitled "canonical representation" in the docs.) Oops, no special modules, you said?...

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://222071]
Approved by fireartist
Front-paged by FamousLongAgo
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others having a coffee break in the Monastery: (6)
As of 2024-03-28 10:21 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found