Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I compare two hashes in Perl without using Data::Compare?

Tags:

hash

perl

How do I compare two hashes in Perl without using Data::Compare?

like image 818
biznez Avatar asked Aug 13 '09 17:08

biznez


4 Answers

The best approach differs according to your purposes. The FAQ item mentioned by Sinan is a good resource: How do I test whether two arrays or hashes are equal?. During development and debugging (and of course when writing unit tests) I have found Test::More to be useful when comparing arrays, hashes, and complex data structures. A simple example:

use strict;
use warnings;

my %some_data = (
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309',
);

my %other_data = (
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309x',
);

use Test::More tests => 1;
is_deeply(\%other_data, \%some_data, 'data structures should be the same');

Output:

1..1
not ok 1 - data structures should be the same
#   Failed test 'data structures should be the same'
#   at _x.pl line 19.
#     Structures begin differing at:
#          $got->{j} = '867-5309x'
#     $expected->{j} = '867-5309'
# Looks like you failed 1 test of 1.
like image 137
FMc Avatar answered Oct 21 '22 16:10

FMc


Compare is not a detailed enough phrase when talking about hashes. There are many ways to compare hashes:

Do they have the same number of keys?

if (%a == %b) {
    print "they have the same number of keys\n";
} else {
    print "they don't have the same number of keys\n";
}

Are the keys the same in both hashes?

if (%a != %b) {
    print "they don't have the same number of keys\n";
} else {
    my %cmp = map { $_ => 1 } keys %a;
    for my $key (keys %b) {
        last unless exists $cmp{$key};
        delete $cmp{$key};
    }
    if (%cmp) {
        print "they don't have the same keys\n";
    } else {
        print "they have the same keys\n";
    }
}

Do they have the same keys and the same values in both hashes?

if (%a != %b) {
    print "they don't have the same number of keys\n";
} else {
    my %cmp = map { $_ => 1 } keys %a;
    for my $key (keys %b) {
        last unless exists $cmp{$key};
        last unless $a{$key} eq $b{$key};
        delete $cmp{$key};
    }
    if (%cmp) {
        print "they don't have the same keys or values\n";
    } else {
        print "they have the same keys or values\n";
    }
}

Are they isomorphic (I will leave this one up to the reader as I don't particularly want to try implementing it from scratch)?

Or some other measure of equal?

And, of course, this code only deals with simple hashes. Adding complex data structures makes it even more complex.

like image 33
Chas. Owens Avatar answered Oct 21 '22 17:10

Chas. Owens


Test::Deep::NoTest has the same functionality.

like image 4
Adam Millerchip Avatar answered Oct 21 '22 16:10

Adam Millerchip


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

Perl's FAQ and answers are part of you Perl distribution. You can view the version of this answer that came with your perl by running:

$ perldoc -q equal

in your terminal.

like image 3
Sinan Ünür Avatar answered Oct 21 '22 15:10

Sinan Ünür