【发布时间】:2010-10-07 02:46:16
【问题描述】:
我想知道是否有一个惯用的单行或标准分发包/函数可以用来比较两个 Perl 哈希与仅内置的非祝福类型。哈希值不相同(它们没有等效的内存地址)。
我想知道浅散列和嵌套集合散列的答案,但我知道浅散列可能有一个更简单的解决方案。
TIA!
【问题讨论】:
标签: perl hash comparison
我想知道是否有一个惯用的单行或标准分发包/函数可以用来比较两个 Perl 哈希与仅内置的非祝福类型。哈希值不相同(它们没有等效的内存地址)。
我想知道浅散列和嵌套集合散列的答案,但我知道浅散列可能有一个更简单的解决方案。
TIA!
【问题讨论】:
标签: perl hash comparison
类似 cmp_deeply 的东西在 Test::Deep 中可用?
【讨论】:
[这是对删除答案的人的回答。]
哦哦!
%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];
【讨论】:
~~ 运算符。 :)
我不知道是否有简单的方法或内置的包,我不知道当你只做%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,对吧?
【讨论】:
感谢您的提问。
我使用了 Test::More::eq_hash 作为结果。
【讨论】:
可以将散列转换为数组,其中每个值都遵循其键(但您不会知道键的顺序)。所以:
( 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>
【讨论】:
对于浅散列:
(grep {exists %hash2{$_}} keys %hash1) > 0
【讨论】:
您可以在Test::Deep::NoTest 中使用eq_deeply。它只返回一个您可以检查的布尔值,而不会产生main module 测试功能的额外开销。
【讨论】:
将哈希转换为 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";
}
}
【讨论】: