比较perl中的多维哈希的最佳方法

时间:2017-08-22 05:18:14

标签: perl hash

我想编写一个脚本,可以比较两个多维哈希,看看它们是否匹配。这两个哈希具有相同的密钥值,比较将在一对中完成,从$j=0首先比较$line[0] $line[1]然后跟$line[2] $line[3]

$hash{"key"}{$key}{"$row $col"}= "$line[$j] $line[$j+1]";
$hash1{"key"}{$key1}{"$row1 $col1"}="$line1[$j] $line1[$j+1]";

我的$ line和$ line1来自一个巨大的文件,并将逐行处理大文件。例如:

@line = 1 2 3 4 5 6 7 8 #fst line from file1
@line1 = 1 2 3 3 4 5 6 7 7 #fst line from file2

$key$key1匹配时,脚本将继续比较$row $col,然后最后比较$line[$j] $line[$j+1]。我正在尝试使用前一个类似问题中提到的模块Test::More之一,但它只能比较第一个不匹配,输出是默认格式。

not ok 1 - data structures should be the same
#   Failed test 'data structures should be the same'
#   at hash_check1.pl line 80.
#     Structures begin differing at:
#          $got->{key}{100}{2 3} = '62 19'
#     $expected->{key}{100}{2 3} = '12 24'
# Tests were run but no plan was declared and done_testing() was not seen.

比较这种类型的多维哈希的最佳方法是什么?

8/22已编辑

如果Test::More模块能够比较两个哈希的所有$key匹配,我也可以采用它,但如果我可以输出匹配和非匹配的我自己的首选格式将是伟大的。例如,我想输出像

$key at $row $col no match with value $line[$j] $line[$j+1] ( expected value $line1[$j] $line1[$j+1] )

8/22已编辑

以下是我的代码的一部分

use strict;
use warnings;
use Test::More;

open ( FILE1 , '<', "file.txt" ) or die $!;
open ( FILE2 , '<' , "file1.txt" ) or die $!;

chomp (my @file1 = <FILE1>);
chomp (my @file2 = <FILE2>);
my %hash=();
my %hash1=();

for ( $i =0 ; $i<=511 ; $i++ ) {
    my @line = split(" ",$file1[$i]);
    my @line1 = split(" ",$file2[$i]);
    my $key = ($i+1)*10;
    my $key1 = ($i+2)*10;

    for ( $j=0; $j<=15 ; $j+=2){
          my $col = hex($j);
          my $col1 = hex($j+1);
          $hash{"key"}{$key}{"$row $col1"}= "$line[$j] $line[$j+1]";
          $hash1{"key"}{$key1}{"$row1 $col1"}= "$line1[$j] $line1[$j+1]";
    }
}

##############comparison part start here###################
is_deeply(\%hash, \%hash1, 'data structures should be the same'); #can only print one mismatch

################Any better way?###########

1 个答案:

答案 0 :(得分:1)

这是一个将嵌套哈希与字符串值进行比较的示例:

#! /usr/bin/env perl

use feature qw(say);
use warnings;
use strict;

my %hash;
my %hash1;

$hash{"key"}{A}{"2 3"}= "1 2";
$hash1{"key"}{A}{"2 3"}="2 3";
$hash{"key"}{B}{"2 3"}= "1 2";
$hash1{"key"}{C}{"2 3"}="2 3";

compare(\%hash, \%hash1);

sub compare {
    return _compare( @_, "" );
}

sub get_key_str { return $_[0] . '{' . $_[1] . '}' }

sub _process_key {
    my ( $h1, $h2, $info, $key, $str1, $str2 ) = @_;

    if ( exists $h2->{$key} ) {
        my $val1 = $h1->{$key};
        my $val2 = $h2->{$key};
        if ( ref $val1 eq "HASH" and ref $val2 eq "HASH" ) {
            _compare( $val1, $val2, get_key_str( $info, $key ) );
        }
        else {
            die "Expected string value" if ref $val1 or ref $val2;
            if ( $val1 ne $val2 ) {
                say "Value '$val1' in $str1 hash for key " . get_key_str( $info, $key )
                  . " does not match value '$val2' in $str2 hash";
            }
        }
    }
    else {
        my $cur_key = get_key_str( $info, $key );
        say "Got key $cur_key in $str1 hash, but missing in $str2 hash"; 
    }
}


sub _compare {
    my ( $h1, $h2, $info ) = @_;

    my %processed_keys;
    for (keys %$h1) {
        _process_key( $h1, $h2, $info, $_, "first", "second" );
        $processed_keys{$_}++;
    }
    for (keys %$h2) {
        next if exists $processed_keys{$_};
        _process_key( $h2, $h1, $info, $_, "second", "first" );
    }
}

<强>输出

Got key {key}{B} in first hash, but missing in second hash
Value '1 2' in first hash for key {key}{A}{2 3} does not match value '2 3' in second hash
Got key {key}{C} in second hash, but missing in first hash