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

A question for the cloister:

We have two arrays that have been sorted. I'm wondering if the straight comparison is good.

@sort_savedpids = sort {$a <=> $b} (@savedpids = get_saved_pids()); @sort_livepids = sort {$a <=> $b} (@livepids = get_live_pids()); if (@sort_savepids ne @sort_livepids ) { <DO STUFF> }
I'm a little concerned that there might be problems with possible 'extra' stuff in the array that might make the two arrays that are otherwise the same come up as not-equal.

Otherwise, would there be a method to cleanse the array to make sure it would just contain numbers? This would probably happen in the get_ routines.

-Kurt

Replies are listed 'Best First'.
Re: Comparing sorted arrays
by vek (Prior) on Jan 15, 2003 at 23:22 UTC
Re: Comparing sorted arrays
by dragonchild (Archbishop) on Jan 15, 2003 at 23:26 UTC
    Well, the straight comparison will tell you if they have the same number of things. (Arrays in scalar context give the number of things in them. Booleans are scalar contexts.)

    You're probably going to have to do a member-wise comparison. Maybe something along the lines of:

    # Using @x and @y in this. sub check { my ($x, $y) = @_; return 0 unless $#$x == $#$y; for (0 .. $#$x) { return 0 if $x->[$_] ne $x->[$_] && $x->[$_] != $x->[$_]; } return 1; }
    The reason for the two comparisons is to make sure that the string comparison doesn't fail with '0' vs '0.0'.

    ------
    We are the carpenters and bricklayers of the Information Age.

    Don't go borrowing trouble. For programmers, this means Worry only about what you need to implement.

Re: Comparing sorted arrays
by Wonko the sane (Curate) on Jan 15, 2003 at 23:33 UTC
    What is actually happening when you
    if (@sort_savepids ne @sort_livepids )
    is that the arrays are getting interpreted in scalar context, which gives you the number of elements in the array.
    Any two arrays with a different amount of elements will pass this test.

    #!/usr/local/bin/perl use strict; my @s1 = qw( a b c ); my @s2 = qw( a b c ); my @s3 = qw( x y z ); print qq{s1 and s2 are equal\n} if ( @s1 eq @s2 ); print qq{s1 and s3 are equal(not really)\n} if ( @s1 eq @s3 );
    Both statements will print out.

    Wonko

Re: Comparing sorted arrays
by jdporter (Paladin) on Jan 16, 2003 at 16:35 UTC
    As others have said, the test you're doing now only tells you whether the two arrays are the same length. While not sufficient, it is certainly a good test to do, since if the two arrays are different lengths, they can't possibly be "equal". So in your array-comparing subroutine, that's the first thing you should do.
    # pass it two arrays, by reference. sub arrays_equal { my( $ar1, $ar2 ) = @_; @$ar1 eq @$ar2 or return 0; # different lengths. # now do member-wise comparison: for my $i ( 0 .. $#{$ar1} ) { $ar1->[$i] eq $ar2->[$i] or return 0; # short circuit } return 1; # all members compared equal. } # call it like so: if ( ! arrays_equal( \@savedpids, \@livepids ) )
    Note that I used string equality. If the arrays are going to contain only numbers, then you'd want to use numeric comparison (==) instead.

    As an added syntactic nicety, you can write this subroutine with a prototype, so you don't have to pass the arrays explicitly as references:
    sub arrays_equal(\@\@) { # everything else is the same } # then you can call it like so: if ( ! arrays_equal( @savedpids, @livepids ) )
    If you use the prototype, however, the declaration of the sub must come before the point of first use.

    jdporter
    The 6th Rule of Perl Club is -- There is no Rule #6.

Re: Comparing sorted arrays
by BrowserUk (Patriarch) on Jan 16, 2003 at 17:06 UTC

    If all you need to know is that the two arrays are the same or not, you can use the fairly quick and dirty trick of stringifying them.

    my @a1 = (...); my @a2 = (...); if ( @a1 == @a2 and do{local $"="\cA"; "@a1"} eq do{local $"="\cA"; "@ +a2"} ) { # They're the same }

    The caveat is that you must choose a delimiter ("\cA" above) that does not appear in your data. Cntrl-A is a fairly safe bet for either text or numeric data, but if your data could include binary data, there is a small chance of a false positive. </code>


    Examine what is said, not who speaks.

    The 7th Rule of perl club is -- pearl clubs are easily damaged. Use a diamond club instead.

      I like your stringification idea. The value of $" doesn't matter though.

      Update: Struck out stupid comment, unfortunately that is not the same as striking out stupidity. I was wrong.