【问题标题】:How do I do a simple Perl hash equivalence comparison?如何进行简单的 Perl 哈希等价比较?
【发布时间】:2010-10-07 02:46:16
【问题描述】:

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

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

TIA!

【问题讨论】:

    标签: perl hash comparison


    【解决方案1】:

    类似 cmp_deeply 的东西在 Test::Deep 中可用?

    【讨论】:

    • 当然,我认为 Test::Deep::eq_deeply 正是我想要的!
    【解决方案2】:

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

    哦哦!

    %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];
    

    【讨论】:

    • '这确实是一个勇敢的 Perl 程序员,敢于​​使用 smarty-pants ~~ 运算符。 :)
    【解决方案3】:

    我不知道是否有简单的方法或内置的包,我不知道当你只做%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,对吧?

    【讨论】:

    • 此外,“==”比较强制标量上下文,因此它比较元素的数量。
    • @cdleary:我这么说是因为,作为 Mac OS X 的用户,所有 OS X 用户在默认情况下仍然使用 5.8.8,除非他们特意升级它。跨度>
    【解决方案4】:

    感谢您的提问。

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

    【讨论】:

      【解决方案5】:

      可以将散列转换为数组,其中每个值都遵循其键(但您不会知道键的顺序)。所以:

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

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

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

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

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

      看起来有点丑,我知道,但它可以用于检查两个哈希是否相等,这是大多数人正在寻找的。​​p>

      【讨论】:

        【解决方案6】:

        对于浅散列:

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

        【讨论】:

          【解决方案7】:

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

          【讨论】:

            【解决方案8】:

            将哈希转换为 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";
                }
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2015-05-13
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-09-05
              • 2011-09-12
              • 1970-01-01
              相关资源
              最近更新 更多