如何在 Perl 中比较两个哈希而不使用 Data::Compare?

问题描述 投票:0回答:7

如何在 Perl 中比较两个哈希而不使用 Data::Compare?

perl hash
7个回答
25
投票

最佳方法根据您的目的而有所不同。 Sinan 提到的常见问题解答项目是一个很好的资源:如何测试两个数组或哈希是否相等?。在开发和调试过程中(当然还有编写单元测试时),我发现

Test::More
在比较数组、哈希和复杂数据结构时非常有用。一个简单的例子:

use strict;
use warnings;

my %some_data = (
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309',
);

my %other_data = (
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309x',
);

use Test::More tests => 1;
is_deeply(\%other_data, \%some_data, 'data structures should be the same');

输出:

1..1
not ok 1 - data structures should be the same
#   Failed test 'data structures should be the same'
#   at _x.pl line 19.
#     Structures begin differing at:
#          $got->{j} = '867-5309x'
#     $expected->{j} = '867-5309'
# Looks like you failed 1 test of 1.

13
投票

在谈论哈希时,比较不是一个足够详细的短语。比较哈希值的方法有很多:

它们的钥匙数量相同吗?

if (%a == %b) {
    print "they have the same number of keys\n";
} else {
    print "they don't have the same number of keys\n";
}

两个哈希中的键是否相同?

if (%a != %b) {
    print "they don't have the same number of keys\n";
} else {
    my %cmp = map { $_ => 1 } keys %a;
    for my $key (keys %b) {
        last unless exists $cmp{$key};
        delete $cmp{$key};
    }
    if (%cmp) {
        print "they don't have the same keys\n";
    } else {
        print "they have the same keys\n";
    }
}

它们在两个哈希中是否具有相同的键和相同的值?

if (%a != %b) {
    print "they don't have the same number of keys\n";
} else {
    my %cmp = map { $_ => 1 } keys %a;
    for my $key (keys %b) {
        last unless exists $cmp{$key};
        last unless $a{$key} eq $b{$key};
        delete $cmp{$key};
    }
    if (%cmp) {
        print "they don't have the same keys or values\n";
    } else {
        print "they have the same keys or values\n";
    }
}

它们是同构的吗(我将把这个问题留给读者,因为我并不是特别想尝试从头开始实现它)?

或者其他一些平等的衡量标准?

当然,这段代码只处理简单的哈希值。添加复杂的数据结构使其变得更加复杂。


4
投票

Test::Deep::NoTest 具有相同的功能。


3
投票

参见 如何测试两个数组或哈希是否相等?

Perl 的常见问题解答和答案是 Perl 发行版的一部分。您可以通过运行以下命令查看您的

perl
附带的此答案的版本:

$ perldoc -q equal

在您的终端中。


2
投票

快速、肮脏,而且我确信效率不高:

use strict;
use warnings;

use Data::Dumper;

sub compare ($$) {
    local $Data::Dumper::Terse  = 1;
    local $Data::Dumper::Indent = 0;
    Dumper(shift) eq Dumper(shift);
}

my %a = ( foo => 'bar', bar => [ 0 .. 3 ] );
my %b = ( foo => 'bar', bar => [ 0 .. 3 ] );
my %c = ( foo => 'bar', bar => [ 0 .. 4 ] );

print Dumper compare \%a, \%b;
print Dumper compare \%a, \%c;

0
投票
use strict;
use warnings;
use JSON::XS;

my $some_data ={
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309',
};

my $other_data = {
    a => [1, 2, 'x'],
    b => { foo => 'bar', biz => 'buz' },
    j => '867-5309x',
};

use Test::More tests => 1;
is_deeply(JSON::XS->new->canonical( 1 )->utf8->encode($other_data), JSON::XS->new->canonical( 1 )->utf8->encode($some_data), 'data structures should be the same');

示例

#   Failed test 'data structures should be the same'
#   at ./t/a.t line 18.
#          got: '{"a":[1,2,"x"],"b":{"biz":"buz","foo":"bar"},"j":"867-5309x"}'
#     expected: '{"a":[1,2,"x"],"b":{"biz":"buz","foo":"bar"},"j":"867-5309"}'
# Looks like you failed 1 test of 1.


-1
投票

用于比较:

sub HashCompare {
  my ( $a, $b ) = @_;
  my %rhash_1 = %$a;
  my %rhash_2 = %$b;

  my $key         = undef;
  my $hash_2_line = undef;
  my $hash_1_line = undef;

  foreach $key ( keys(%rhash_2) ) {
   if ( exists( $rhash_1{$key} ) ) {
    if ( $rhash_1{$key} ne $rhash_2{$key} ) {
     print "key $key in $file_1 = $rhash_1{$key} & $rhash_2{$key} in $file_2\n";
         }
       }
     }
     else {
        print "key $key in  $file_1 is not present in $file_2\n";

            #next;
        }
    }

    foreach my $comp_key ( keys %rhash_1 ) {
        if ( !exists( $rhash_2{$comp_key} ) ) {
            print MYFILE "key $comp_key in  $file_2 is not present in $file_1\n";
        }
    }
    return;
}

创建没有重复键的哈希:

sub CreateHash {
    my (@key_val_file ) = @_;
    my $key_count      = 1;
    my %hash_key_val   = ();
    my $str4           = undef;

    local $/ = undef;

    foreach my $each_line (@key_val_file) {
            @key_val = split( /,/, $each_line );
            if ( exists( $hash_key_val{$key_val[0]} ) ) {
                    $key_count = $key_count + 1;
                    $str4      = $key_val[0] . " occurence-" . $key_count;
                    $hash_key_val{$str4} = $key_val[1];
                }
                else {
                    $hash_key_val{$key_name} = $key_val[1];
                }
            }
        }

        $key_count = 1;

    close FILE;

    return %hash_key_val;
}
© www.soinside.com 2019 - 2024. All rights reserved.