在 Perl 中测试两个哈希键是不是具有相同的结构
Posted
技术标签:
【中文标题】在 Perl 中测试两个哈希键是不是具有相同的结构【英文标题】:Testing that two hash keys have equal structures in Perl在 Perl 中测试两个哈希键是否具有相同的结构 【发布时间】:2021-11-23 18:41:33 【问题描述】:我正在编写一个单元测试,我必须检查两个散列变量(散列的散列)的关键结构是否相同。键值可以不同。哈希的深度是任意的。
Test::Deep
看起来很理想,但我不知道如何让cmp_deeply
忽略这些值。
use Test::Deep;
my %hash1 = ( key1 => "foo", key2 => key21 => "bar", key22 => "yeah");
my %hash2 = ( key1 => "foo", key2 => key21 => "bar", key22 => "wow");
cmp_deeply(\%hash1, \%hash2, "This test should not fail");
输出:
not ok 1 - This test should not fail
# Failed test 'This test should not fail'
# at demo.pl line 13.
# Compared $data->"key2""key22"
# got : 'yeah'
# expect : 'wow'
如果哈希具有已知结构,我可以使用值为ignore()
的测试变量。但是,就我而言,最好的解决方案是我不必更新测试代码中的结构。
我尝试使用Data::Walk
遍历%hash1
并检查%hash2
中是否存在每个键,但发现很难从$Data::Walk::container
值中获取当前键。
对于合适的比较工具有什么想法吗?
【问题讨论】:
【参考方案1】:您似乎需要忽略这些结构中的叶子,否则会进行比较。
然后可以比较两个结构之间到叶子的所有路径,忽略叶子。
Data::Leaf::Walker 模块可以帮助生成所有叶子的路径数组。然后需要比较这些,Test::Deep
及其包比较只是工具。
use warnings;
use strict;
use feature 'say';
use Data::Leaf::Walker;
use Test::More qw(no_plan);
use Test::Deep;
my %h1 = (key1 => "foo", key2 => key21 => "bar", key22 => "yeah");
my %h2 = (key1 => "foo", key2 => key21 => "bar", key22 => "wow");
my @key_paths_h1 = Data::Leaf::Walker->new(\%h1)->keys;
my @key_paths_h2 = Data::Leaf::Walker->new(\%h2)->keys;
# Now compare @key_paths_h1 and @key_paths_h2
# Order of arrayrefs in the top-level arrays doesn't matter
# but order of elements in each arrayref does
cmp_bag(\@key_paths_h1, \@key_paths_h2, 'key-paths');
这会按预期打印,ok 1 - key-paths
。更改任何键都以not ok 1 ...
结束
说到这里,我想提一下这个模块提供了一个迭代器
my $walker = Data::Leaf::Walker->new($data_structure_ref);
while ( my ($keys_path, $value) = $walker->each )
say "[ @$keys_path ] => $value"
这样我们可以同时获得路径和它们的值,一次弹出一个。只有几个,但选择得当,方法。请参阅文档。
【讨论】:
【参考方案2】:这是一个手动操作的示例:
use strict;
use warnings;
use experimental qw(signatures);
use Test::More;
my %hash1 = ( key1 => "foo", key2 => key21 => "bar", key22 => "yeah");
my %hash2 = ( key1 => "foo", key2 => key21 => "bar", key22 => "wow");
ok(cmp_keys(\%hash1, \%hash2), "Hash keys identical");
done_testing();
sub cmp_keys( $hash1, $hash2 )
my @keys1 = flatten_keys( $hash1 );
my @keys2 = flatten_keys( $hash2 );
return 0 if @keys1 != @keys2;
for my $i (0..$#keys1)
return 0 if $keys1[$i] ne $keys2[$i];
return 1;
sub flatten_keys( $hash )
my @keys;
my $prefix = '';
_flatten_keys( $hash, $prefix, \@keys);
return sort @keys;
sub _flatten_keys ( $hash, $prefix, $keys)
# $; The subscript separator for multidimensional array emulation,
# default value is "\034" = 0x1C
my $sep = $;;
for my $key (keys %$hash)
if (ref $hash->$key eq "HASH")
_flatten_keys( $hash->$key, $prefix . $key . $sep, $keys );
push @$keys, $prefix . $key;
【讨论】:
以上是关于在 Perl 中测试两个哈希键是不是具有相同的结构的主要内容,如果未能解决你的问题,请参考以下文章
是否有简单的语法用于在 perl 中声明具有一个值的多个键?