开发者

How can I compare two sets of hash references using Perl?

开发者 https://www.devze.com 2023-01-22 18:32 出处:网络
So I have two files with similar information. EXAMPLES test.txt 1=1 2=2 3=3 test_2.txt 1=1 2=4 3=5 4=4 5=5 6=6 Now I want to print each hashes keys and values.

So I have two files with similar information.

EXAMPLES

test.txt

1=1

2=2

3=3

test_2.txt

1=1

2=4

3=5

4=4

5=5

6=6

Now I want to print each hashes keys and values.

my %hash1;  
my $scalar_value1;  
my $scalar_value2;  
my $file = "/test/test.txt";  
open (TEST, "<$file") or die "$!";  
while (TEST) {  
            ($scalar_value1, $scalar_value2) = split( '=' );  
            $hash1{$scalar_value1}{'value1'} = $scalar_value1;  
            $hash1{$scalar_value1}{'value2'} = $scalar_value2;  
        }  
close TEST;  

foreach my $scalar_value1 (sort keys %hash1) {  
        print "$hash1{$scalar_value1}{'value1'} | $hash1{$scalar_value1}{'value2'}";  
}  


my %hash2;  
my $scalar_value_1_2;  
my $scalar_value_2_2;  
my $file_2 = "/test/test2.txt";  
open (TEST_2, "<$file_2") or die "$!";  
while (TEST_2) {  
            ($scalar_value_1_2, $scalar_value_2_2) = split( '=' );  
            $hash1{$scalar_value_1_2}{'value_1_2'} = $scalar_value_1_2;  
            $hash1{$scalar_value_1_2}{'value_2_2'} = $scalar_value_2_2;  
        }  
close TEST_2;  

foreach my $scalar_value_1_2 (sort keys %hash1) {  
        print "$hash1{$scalar_value_1_2}{'value1_2'} | $hash1{$scalar_value_1_2}{'value1_2'}";  
}    

Now how can I compare the two hashes to produce a new value based on wh开发者_StackOverflow中文版ether or not the first hash contained a similar key?

if ($hash1{$scalar_value_1_2}{'value1_2} eq $hash1{$scalar_value1}{'value1'}) {  
    my $scalar_value_2_2; = $hash1{$scalar_value1}{'value2'};  
    print "YES MATCH: $scalar_value_2_2\n";  
} else {  
    print "N0 MATCH: $scalar_value_2_2\n";  
}  


I rewrote your program for better clarity. "chomp" is important to include to remove new line.

use strict;
use warnings;
sub read_hash {
    my $fname = shift;
    open (my $fh, "<",$fname) or die "$!";  
    my %hash;
    while (<$fh>) {
        chomp;
        my ($key,$value)=split /=/;
        $hash{$key}=$value;
    }
    return %hash;
}

my %hash1=read_hash("test.txt");

foreach my $key (sort keys %hash1) {  
        print "$key = $hash1{$key}\n";
}  

my %hash2=read_hash("test1.txt");

foreach my $key (sort keys %hash2) {  
        print "$key = $hash2{$key}\n";
}  


#------------------------

foreach my $key (sort keys %hash2) {  
        if (exists $hash1{$key}) {
            print "$key exists in first hash\n";
        } else {
            print "$key does not exist in first hash\n";
        }
}  


Sounds like a simple set intersection problem. Here's a reshuffled version of the code using Alexandr's work.

use strict;
use warnings;
sub read_hash {
    my $fname = shift;
    open (my $fh, "<",$fname) or die "$!";  
    my %hash;
    while (<$fh>) {
        chomp;
        my ($key,$value)=split /=/;
        $hash{$key}=$value;
    }
    # let's retrun the reference here. With big hashes, you want to avoid copying
    return \%hash;
}

my $h1=read_hash("test.txt");
my $h2=read_hash("test1.txt");

map {print "$_ = $h1->{$_}\n"} sort keys %$h1;
map {print "$_ = $h2->{$_}\n"} sort keys %$h2;

map {print "key from h1 $_ exists in h2\n" if exists $h2->{$_} } sort keys %$h1; 

# if you just want to take out the items from $h2 that also exists in $h1.
my %h3 = map {$_=>$h2->{$_} if exists $h2->{$_}} keys %$h1;

Notice that the program uses map to do list iteration. The last usage of map creates a hash that contains the intersection of the keys of the 2 hashes. In order to optimize the code further, I would iterate through the hash that has less number of keys. Also note that the methods above does not check the value of the keys. It only compares the keys themselves.

Hope this helps.

0

精彩评论

暂无评论...
验证码 换一张
取 消