biznez
biznez

Reputation: 4021

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

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

Upvotes: 19

Views: 47372

Answers (7)

Baryshev Sergey
Baryshev Sergey

Reputation: 1

use strict;
use warnings;
use JSON::XS;

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(JSON::XS->new->canonical( 1 )->utf8->encode($other_data), JSON::XS->new->canonical( 1 )->utf8->encode($some_data), 'data structures should be the same');

Example

#   Failed test 'data structures should be the same'
#   at ./t/a.t line 18.
#          got: '{"a":[1,2,"x"],"b":{"biz":"buz","foo":"bar"},"j":"867-5309x"}'
#     expected: '{"a":[1,2,"x"],"b":{"biz":"buz","foo":"bar"},"j":"867-5309"}'
# Looks like you failed 1 test of 1.

use strict;
use warnings;
use JSON::XS;

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-5309',
};

use Test::More tests => 1;
is_deeply(JSON::XS->new->canonical( 1 )->utf8->encode($other_data), JSON::XS->new->canonical( 1 )->utf8->encode($some_data), 'data structures should be the same');

Example2

All tests successful.

Upvotes: -1

FMc
FMc

Reputation: 42421

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.

Upvotes: 25

Sinan Ünür
Sinan Ünür

Reputation: 118166

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.

Upvotes: 4

Adam Millerchip
Adam Millerchip

Reputation: 23147

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

Upvotes: 4

Sourcecode
Sourcecode

Reputation: 315

For comparing:

sub HashCompare {
  my ( $a, $b ) = @_;
  my %rhash_1 = %$a;
  my %rhash_2 = %$b;

  my $key         = undef;
  my $hash_2_line = undef;
  my $hash_1_line = undef;

  foreach $key ( keys(%rhash_2) ) {
   if ( exists( $rhash_1{$key} ) ) {
    if ( $rhash_1{$key} ne $rhash_2{$key} ) {
     print "key $key in $file_1 = $rhash_1{$key} & $rhash_2{$key} in $file_2\n";
         }
       }
     }
     else {
        print "key $key in  $file_1 is not present in $file_2\n";

            #next;
        }
    }

    foreach my $comp_key ( keys %rhash_1 ) {
        if ( !exists( $rhash_2{$comp_key} ) ) {
            print MYFILE "key $comp_key in  $file_2 is not present in $file_1\n";
        }
    }
    return;
}

Creating hash with no duplicate keys:

sub CreateHash {
    my (@key_val_file ) = @_;
    my $key_count      = 1;
    my %hash_key_val   = ();
    my $str4           = undef;

    local $/ = undef;

    foreach my $each_line (@key_val_file) {
            @key_val = split( /,/, $each_line );
            if ( exists( $hash_key_val{$key_val[0]} ) ) {
                    $key_count = $key_count + 1;
                    $str4      = $key_val[0] . " occurence-" . $key_count;
                    $hash_key_val{$str4} = $key_val[1];
                }
                else {
                    $hash_key_val{$key_name} = $key_val[1];
                }
            }
        }

        $key_count = 1;

    close FILE;

    return %hash_key_val;
}

Upvotes: -1

zakovyrya
zakovyrya

Reputation: 9689

Quick, dirty, and I'm sure not that efficient:

use strict;
use warnings;

use Data::Dumper;

sub compare ($$) {
    local $Data::Dumper::Terse  = 1;
    local $Data::Dumper::Indent = 0;
    Dumper(shift) eq Dumper(shift);
}

my %a = ( foo => 'bar', bar => [ 0 .. 3 ] );
my %b = ( foo => 'bar', bar => [ 0 .. 3 ] );
my %c = ( foo => 'bar', bar => [ 0 .. 4 ] );

print Dumper compare \%a, \%b;
print Dumper compare \%a, \%c;

Upvotes: 2

Chas. Owens
Chas. Owens

Reputation: 64939

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.

Upvotes: 14

Related Questions