出于学术目的,这是一个相当整洁的递归函数:
sub flatten_hash {
my ($hash, $path) = @_;
$path = [] unless defined $path;
my @ret;
while (my ($key, $value) = each %$hash) {
if (ref $value eq 'HASH') {
push @ret, flatten_hash($value, [ @$path, $key ]);
} else {
push @ret, [ [ @$path, $key ], $value ];
}
}
return @ret;
}
它采用像
这样的哈希值
{
roman => {
i => 1,
ii => 2,
iii => 3,
},
english => {
one => 1,
two => 2,
three => 3,
},
}
把它变成一个类似的列表
(
[ ['roman','i'], 1 ],
[ ['roman', 'ii'], 2 ],
[ ['roman', 'iii'], 3 ],
[ ['english', 'one'], 1 ],
[ ['english', 'two'], 2 ],
[ ['english', 'three'], 3 ]
)
当然,顺序肯定会有所不同。给定该列表,您可以按{ $a->[1] <=> $b->[1] } 或类似名称对其进行排序,然后从@{ $entry->[0] } 中提取每个条目的键路径。无论数据结构的深度如何,它都可以工作,即使叶节点没有出现在相同的深度。不过,它需要一些扩展来处理不是纯粹的 hashrefs 和普通标量的结构。