Perl中如何比对两个任意深度哈希的键结构,忽略值差异
嵌套哈希键结构比对实现方案
方案1:基于Test::Deep实现(推荐)
你可以通过一个简单的递归函数,自动将参考哈希的所有值替换为ignore()对象,即可实现仅校验键结构、忽略值比对的需求:
use Test::Deep; # 递归将哈希所有值替换为ignore(),保留键结构 sub hash_structure { my ($hash_ref) = @_; my %struct; while (my ($k, $v) = each %$hash_ref) { $struct{$k} = ref $v eq 'HASH' ? hash_structure($v) : ignore(); } return \%struct; } # 测试用例 my %hash1 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "yeah"}); my %hash2 = ( key1 => "foo", key2 => {key21 => "bar", key22 => "wow"}); cmp_deeply(\%hash1, hash_structure(\%hash2), "键结构一致测试通过"); # 如果需要双向校验结构完全一致,再加一行反向校验即可 cmp_deeply(\%hash2, hash_structure(\%hash1), "双向校验键结构完全一致");
如果你的嵌套结构中可能包含数组,可扩展上述函数增加数组类型的判断逻辑,对应递归处理数组元素的结构即可。
方案2:无依赖独立递归校验函数
如果你不想依赖Test::Deep,也可以自己实现双向键结构校验,还可以自定义错误提示的键路径:
sub check_hash_key_structure { my ($hash1, $hash2, $path) = @_; $path //= ''; # 先校验当前层级键数量一致 my @keys1 = keys %$hash1; my @keys2 = keys %$hash2; return (0, "键数量不一致,路径$path 左侧有".@keys1."个键,右侧有".@keys2."个键") unless @keys1 == @keys2; # 校验所有键双向存在、嵌套结构类型一致 for my $k (@keys1) { return (0, "键不存在:路径$path\->{$k} 仅左侧存在") unless exists $hash2->{$k}; my $new_path = $path ? "$path\->{$k}" : "{$k}"; # 如果值是哈希类型,递归校验下一层结构 if (ref $hash1->{$k} eq 'HASH') { return (0, "类型不一致:路径$new_path 左侧是HASH,右侧不是") unless ref $hash2->{$k} eq 'HASH'; my ($ok, $err) = check_hash_key_structure($hash1->{$k}, $hash2->{$k}, $new_path); return ($ok, $err) unless $ok; } } return (1, "键结构完全一致"); } # 使用示例 my ($ok, $err) = check_hash_key_structure(\%hash1, \%hash2); ok($ok, $err);
内容的提问来源于stack exchange,提问作者Matti Lattu
相关产品推荐
相关产品推荐

