【问题标题】:How can I compare two sets of hash references using Perl?如何使用 Perl 比较两组哈希引用?
【发布时间】:2010-11-02 05:12:46
【问题描述】:

所以我有两个信息相似的文件。

示例

test.txt
1=1
2=2
3=3

test_2.txt
1=1
2=4
3=5
4=4
5=5
6=6

现在我想打印每个哈希键和值。

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'}";  
}    

现在如何根据第一个散列是否包含相似键来比较两个散列以生成新值?

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";  
}  

【问题讨论】:

  • 查看侧边栏中的所有“相关”链接——在前几个链接中可以有类似的算法。

标签: perl hash


【解决方案1】:

为了更清晰,我重写了你的程序。 “chomp”对于删除新行很重要。

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";
        }
}  

【讨论】:

  • 如果第一个哈希引用只记住第一个哈希的最后一个键和值怎么办?
  • 卢克:你有像“key=value”这样的行的文件。 “key”可以在同一个文件中重复吗?
  • 是的,键值可以在文件中重复。
  • 在子例程中总是 local $_;while (&lt;handle&gt;) {...} 之前。没有本地,这是一个等待发生的错误
  • 卢克:您需要创建对数组的引用作为哈希值并推送到它。
【解决方案2】:

听起来像是一个简单的集合交集问题。这是使用 Alexandr 工作的代码的改组版本。

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;

请注意,程序使用 map 来进行列表迭代。 map 的最后一次使用创建了一个包含 2 个哈希键的交集的哈希。为了进一步优化代码,我将遍历键数较少的散列。另请注意,上述方法不会检查键的值。它只比较密钥本身。

希望这会有所帮助。

【讨论】:

  • 为什么要使用地图打印? foreach 在这里更好。
  • 确实如此。 foreach 更适合打印。感谢您的来信。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-03-31
  • 1970-01-01
  • 2016-09-05
  • 1970-01-01
  • 2011-09-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多