CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
Better way to compare two hashes

 



rietchel
New User

Apr 30, 2017, 7:38 PM

Post #1 of 3 (419 views)
Better way to compare two hashes Can't Post

Hi,

I'm looking for a better way to compare two hashes (or hash of hashes), possibly via map or grep, however I can seem to wrap my head something that doesn't use a for loop. This is the current method I'm using:

First compare each hash key, by key. If the keys are the same then compare the values. Then print out either matching or mismatching.

Here's a simple example:



Code
 
my %first_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "bar_3",
);

my %second_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "ERR",
);

my %matching;
my %mismatching;

# comparing hashes

foreach my $first_key (%first_hash) {
foreach my $second_key (%second_hash) {
if ($first_key eq $second_key) {

my $first_value = $first_hash{$first_key};
my $second_value = $second_hash{$second_hash};

if ($first_value eq $second_value) {
print "Matching: First Val: $first_value Second Val: $second_value";
} else {
print "Mismatching: First Val: $first_value Second Val: $second_value";
}
}
}


In The above example the output would look like:


Code
 
Matching: First Val: bar_1 Second Val: bar_1
Matching: First Val: bar_2 Second Val: bar_2
Mismatching: First Val: bar_3 Second Val: ERR


Now I know this method works, however once I start getting into hash of hashes it gets a bit messy having a ton of nested for loops. Is this even possible without using for loops?

Thanks!


Chris Charley
User

May 1, 2017, 10:20 AM

Post #2 of 3 (402 views)
Re: [rietchel] Better way to compare two hashes [In reply to] Can't Post

This link shows how to compare 2 hashes but it doesn't list the actual differences.


(This post was edited by Chris Charley on May 1, 2017, 10:21 AM)


BillKSmith
Veteran

May 1, 2017, 10:45 AM

Post #3 of 3 (397 views)
Re: [rietchel] Better way to compare two hashes [In reply to] Can't Post

Your looping is much to complex to accomplish what you do. Use:

Code
use strict; 
use warnings;

my %first_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "bar_3",
);

my %second_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "ERR",
#"foo_3" => "bar_3",
);
foreach my $key (keys %first_hash) {
if ( $first_hash{$key} eq $second_hash{$key} ) {
printf "Matching: First Val: %5s Second Val: %5s\n",
$first_hash{$key}, $second_hash{$key};
}
else{
printf "Mismatching: First Val: %5s Second Val: %5s\n",
$first_hash{$key}, $second_hash{$key};
}
}


If you really want all the printing, I would not recommend map or grep. If you only need to know whether or not the hashes match, you could use grep. However the logic is much clearer if you use a grep-like function from the module List::MoreUtils.


Code
use strict; 
use warnings;
use List::MoreUtils qw(all);

my %first_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "bar_3",
);

my %second_hash = (
"foo_1" => "bar_1",
"foo_2" => "bar_2",
"foo_3" => "ERR",
#"foo_3" => "bar_3",
);

my $match = all {$first_hash{$_} eq $second_hash{$_} } keys %first_hash;

die "Hashes do not match\n" if (!defined $match);
print "Hashes do match\n";


Your method and mine only work correctly when the hashes contain the same set of keys. If not, You must specify exactly what you want before you can code the test.

Probably the best way to generalize to a hash of hashes is to use a recursive subroutine.
Good Luck,
Bill

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives