FAQ 4.44 How do I test whether two arrays or hashes are equal?

Discussion in 'Perl Misc' started by PerlFAQ Server, Apr 20, 2011.

  1. This is an excerpt from the latest version perlfaq4.pod, which
    comes with the standard Perl distribution. These postings aim to
    reduce the number of repeated questions as well as allow the community
    to review and update the answers. The latest version of the complete
    perlfaq is at http://faq.perl.org .

    --------------------------------------------------------------------

    4.44: How do I test whether two arrays or hashes are equal?

    With Perl 5.10 and later, the smart match operator can give you the
    answer with the least amount of work:

    use 5.010;

    if( @array1 ~~ @array2 )
    {
    say "The arrays are the same";
    }

    if( %hash1 ~~ %hash2 ) # doesn't check values!
    {
    say "The hash keys are the same";
    }

    The following code works for single-level arrays. It uses a stringwise
    comparison, and does not distinguish defined versus undefined empty
    strings. Modify if you have other needs.

    $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;
    }

    For multilevel structures, you may wish to use an approach more like
    this one. It uses the CPAN module "FreezeThaw":

    use FreezeThaw qw(cmpStr);
    @a = @b = ( "this", "that", [ "more", "stuff" ] );

    printf "a and b contain %s arrays\n",
    cmpStr(\@a, \@b) == 0
    ? "the same"
    : "different";

    This approach also works for comparing hashes. Here we'll demonstrate
    two different answers:

    use FreezeThaw qw(cmpStr cmpStrHard);

    %a = %b = ( "this" => "that", "extra" => [ "more", "stuff" ] );
    $a{EXTRA} = \%b;
    $b{EXTRA} = \%a;

    printf "a and b contain %s hashes\n",
    cmpStr(\%a, \%b) == 0 ? "the same" : "different";

    printf "a and b contain %s hashes\n",
    cmpStrHard(\%a, \%b) == 0 ? "the same" : "different";

    The first reports that both those the hashes contain the same data,
    while the second reports that they do not. Which you prefer is left as
    an exercise to the reader.



    --------------------------------------------------------------------

    The perlfaq-workers, a group of volunteers, maintain the perlfaq. They
    are not necessarily experts in every domain where Perl might show up,
    so please include as much information as possible and relevant in any
    corrections. The perlfaq-workers also don't have access to every
    operating system or platform, so please include relevant details for
    corrections to examples that do not work on particular platforms.
    Working code is greatly appreciated.

    If you'd like to help maintain the perlfaq, see the details in
    perlfaq.pod.
     
    PerlFAQ Server, Apr 20, 2011
    #1
    1. Advertising

  2. PerlFAQ Server

    John Bokma Guest

    "John Small" <> writes:

    > But all the elements in the arrays being compared in this particular
    > program are all single "words". For this situation "@array1" eq
    > "@array2" does seem to work. Is there any reason to think "@array1" eq
    > "@array2" would not work under these conditions?


    If these conditions always hold, it will always work. Note that the FAQ
    answer has also specific conditions, and fails if those conditions don't
    hold.

    --
    John Bokma j3b

    Blog: http://johnbokma.com/ Facebook: http://www.facebook.com/j.j.j.bokma
    Freelance Perl & Python Development: http://castleamber.com/
     
    John Bokma, Apr 22, 2011
    #2
    1. Advertising

  3. PerlFAQ Server

    Dr.Ruud Guest

    On 2011-04-21 13:07, John Small wrote:

    > if ("@array1" eq "@array2") ...
    >
    > This seems to work for me.


    Having parallel arrays is often a design flaw.

    Replace for example by a hash, where the value is a counter.

    perl -MData::Dumper -MList::MoreUtils=uniq -wle '
    my @old = qw/ a b c d e f g h i j /;
    my @new = qw/ 2 7 d e j k l /;
    my %uniq;

    ++$_ for @uniq{ @old };
    --$_ for @uniq{ @new };
    delete @uniq{ grep !$uniq{ $_ }, keys %uniq };

    print Dumper( \%uniq );

    print uniq sort @old, @new;
    '

    --
    Ruud
     
    Dr.Ruud, Apr 22, 2011
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Yves Glodt

    test whether 2 objects are equal

    Yves Glodt, Jan 31, 2006, in forum: Python
    Replies:
    5
    Views:
    327
    Bruno Desthuilliers
    Feb 1, 2006
  2. Kev Jackson
    Replies:
    2
    Views:
    141
  3. Tim O'Donovan

    Hash of hashes, of hashes, of arrays of hashes

    Tim O'Donovan, Oct 27, 2005, in forum: Perl Misc
    Replies:
    5
    Views:
    233
  4. PerlFAQ Server
    Replies:
    0
    Views:
    286
    PerlFAQ Server
    Feb 2, 2011
  5. PerlFAQ Server
    Replies:
    0
    Views:
    130
    PerlFAQ Server
    Apr 21, 2011
Loading...

Share This Page