如何进行简单的Perl哈希等价比较?

时间:2009-02-12 06:01:07

标签: perl hash comparison

我想知道是否有一个惯用的单行或标准分发包/函数,我可以用来比较两个Perl哈希只有内置的,非祝福的类型。哈希值不相同(它们没有等效的内存地址)。

我想知道浅层哈希和嵌套集合哈希的答案,但我知道浅哈希可能有一个更简单的解决方案。

TIA!

8 个答案:

答案 0 :(得分:13)

Test::Deep中可以使用cmp_deeply吗?

答案 1 :(得分:4)

[这是对删除答案的人的答复的回应。]

哦,哦!

%a ~~ %b && [sort values %a] ~~ [sort values %b]

不检查值是否属于相同的键。

#! perl
use warnings;
use strict;

my %a = (eat => "banana", say => "whu whu"); # monkey
my %b = (eat => "whu whu", say => "banana"); # gorilla
print "Magilla Gorilla is always right\n" 
    if %a ~~ %b && [sort values %a] ~~ [sort values %b];

答案 2 :(得分:1)

我不知道是否有简单的方法或内置的软件包,我不知道当你做%hash1 == %hash2时会发生什么(但可能不是这样),但它并不是特别困难滚动你自己:

sub hash_comp (\%\%) {
  my %hash1 = %{ shift };
  my %hash2 = %{ shift };
  foreach (keys %hash1) {
    return 1 unless defined $hash2{$_} and $hash1{$_} == $hash2{$_};
    delete $hash1{$_};
    delete $hash2{$_};
  }
  return 1 if keys $hash2;
  return 0;
}

未经测试,但如果哈希具有所有相同的元素和所有相同的值,则应返回0。必须修改此函数以考虑多维哈希。

如果你想要标准发行版的内容,你可以use Data::Dumper;并将两个哈希值转换为两个标量变量,然后比较字符串的相等性。这可能有用。

CPAN上还有一个名为FreezeThaw的软件包看起来像你想做的那样。

请注意,要使用智能匹配(此处不重复,因为它已经发布),您必须use feature;并且它仅适用于Perl 5.10。但是谁还在使用Perl 5.8.8,对吧?

答案 3 :(得分:1)

感谢您的提问。

我使用了Test :: More :: eq_hash作为结果。

答案 4 :(得分:0)

浅浅的哈希:

(grep {exists %hash2{$_}} keys %hash1) > 0

答案 5 :(得分:0)

哈希可以被转换为数组,其中每个值都跟随其键(但您不会知道键的顺序)。所以:

( join("",sort(%hash1)) eq join("",sort(%hash2)) )

哦,等等,这是行不通的,因为有一些边缘情况,例如:

%hash1 = { 'aaa' => 'aa'  };
%hash2 = { 'aa'  => 'aaa' };

所以最好在join()中使用一个你知道永远不会出现在任何键或值中的字符。如果值是BLOB,那将是一个大问题,但对于其他任何事情,您可以使用NULL char“\ 0”。

( join("\0",sort(%hash1)) eq join("\0",sort(%hash2)) )

看起来有点难看,我知道,但它会检查两个哈希值是否相等,这是大多数人都在寻找的。

答案 6 :(得分:0)

您可以在eq_deeply中使用Test::Deep::NoTest。它只返回一个你可以检查的布尔值,而没有main module的测试功能的额外开销。

答案 7 :(得分:-1)

将哈希转换为xml文件并进行比较,是的,您可以使用多级。

sub isEqualHash 
{
    my ($self,$hash1, $hash2) = @_;
    my  $file1 = "c:/neo-file1.txt";
    my  $file2 = "c:/neo-file2.txt";
    my $xmlObj = XML::Simple->new();
    my $dummy_file = $xmlObj->XMLout($hash1,OutputFile => $file1);
    my $dummy_file = $xmlObj->XMLout($hash2,OutputFile => $file2);

    open FILE, "<".$file1;
    my $file_contents1 = do { local $/; <FILE> };
    close(FILE);

    open FILE, "<".$file2;
    my $file_contents2 = do { local $/; <FILE> };
    close(FILE);

    if($file_contents1 eq $file_contents2)
    {
        return "Passed";
    }
    else
    {
        return "Failed";
    }
}