Re: How to test equality of hashes?

by jeroenes (Priest)
 on Jun 20, 2001 at 12:05 UTC ( #89938=note: print w/replies, xml ) Need Help??

in reply to How to test equality of hashes?

bikeNomad's solution 1 does not take into account the probability that the values may be the same, but that they are not tied to the same key. So:
```my @k1 = keys(%hash1);
my @k2 = keys(%hash2);

# do they have the same number of elements?
if (@k1 != @k2) { # they're different...
}

# are the keys the same?
if ((join \$; , sort @k1 )
ne join \$; , sort @k2)) { #they're different
}

# are the values the same?
if ( scalar grep { \$hash1{\$_} ne \$hash2{\$_} } @k1 )
{ #they're different
}
Number warning still applies.

Jeroen

Replies are listed 'Best First'.
Re: Re: How to test equality of hashes?
by acser (Novice) on Jun 20, 2001 at 17:56 UTC
Here's the subroutine I came up with. Thanks for everyone who responded. I could never get the flattening the array method to work. It is not very elegant and probably slow, but this is the only solution I could find that prints the right answer:
```equal

non equal

equal
```#!/usr/bin/perl
\$HASH_SIZE = 100;
%hash1;
%hash2;

for (\$i=0; \$i < \$HASH_SIZE; \$i++) {
\$hash1{"i=\$i"} = "j=\$i";
}

%hash2 = %hash1;

if (&hasheq(\%hash1, \%hash2)) {
print "\nequal\n";
} else
{
print "\nnon equal\n";
}

\$hash2{"anotherone"} = "anotherONE";

if (&hasheq(\%hash1, \%hash2)) {
print "\nequal\n";
} else
{
print "\nnon equal\n";
}

\$hash1{"anotherone"} = "anotherONE";

if (&hasheq(\%hash1, \%hash2)) {
print "\nequal\n";
} else
{
print "\nnon equal\n";
}

sub hasheq {

my (\$ha1, \$ha2) = @_;
my %h1 = %\$ha1;
my %h2 = %\$ha2;

my @k1 = keys(%h1);
my @k2 = keys(%h2);
# do they have the same number of elements?
if (@k1 != @k2) {
return 0;
}

# are the keys the same?
if ((join '/' , sort @k1 ) ne (join '/' , sort @k2)) {
return 0;
}

# are the values the same?
if ( scalar grep { \$h1{\$_} ne \$h2{\$_} } @k1 )
{
return 0;
}

return 1;

}
Nice. I can't see this kind of follow-ups often enough!

1. use strict warnings and diagnostics or die. These are your friends on the long run.
2. You declare 2 vars without need:
```  my %h1 = %{ \$_[0] }; #h2 similar
3. Check whether your refs are defined:
```  my %h1 = (defined \$_[0] and ref \$_[0]) ? %{ \$_[0] } : ();
This will make the code more portable/general/cleaner. You may add an extra check for hashiness.
4. I just realized that this code can't distinguish between undefined or empty, so the grep becomes:
```  scalar grep {
my (\$a, \$b) = ( \$h1{\$_}, \$h2{\$_} );
( not defined \$a and defined \$b )
or
( not defined \$b and defined \$a )
or
\$a ne \$b
} @k1
Had to think extra carefully there!

Hope this helps,

Jeroen

Create A New User
Node Status?
node history
Node Type: note [id://89938]
help
Chatterbox?
 [marinersk]: That would mitigate the distraction/jangle issue, but then the information wouldn't be easy to find when it is populated. Plus, I don't currently see a way to move it, but I'm not done poking around on that point yet. [marinersk]: Ah, you beat me to it. [LanX]: as long as he has votes left, the nodelet remains [LanX]: There is a very simple solution ... [marinersk]: Correct, so one workaround is to leave one vote. [marinersk]: But I was looking for a more elegant solution. It appears noone online at this time is aware of one. [LanX]: go to Nodelet Settings and click "All nodelets off"

How do I use this? | Other CB clients
Other Users?
Others having an uproarious good time at the Monastery: (9)
As of 2017-05-29 14:14 GMT
Sections?
Information?
Find Nodes?
Leftovers?
Voting Booth?
My favorite model of computation is ...

Results (192 votes). Check out past polls.