众所周知如何在perl中迭代哈希(参见例如What's the safest way to iterate through the keys of a Perl hash?)。但是,键和值的顺序是不确定的,实际上每次运行perl脚本都是不同的。
有没有办法确保同一输入数据上相同perl脚本的每次运行都会产生相同的迭代顺序?我只关心这种意义上的可复制性 - 命令不需要被人类预测。
编辑:我在迭代方面提出了问题,但也许它不是哈希的迭代,而是哈希构建过程是非确定性的。我可以设置一些初始化来以确定性和可复制的方式构建哈希吗?答案 0 :(得分:6)
sort
:
foreach my $key ( sort keys %hash ) {
}
注意:默认排序是按字母顺序排列的,而不是数字排序。但是sort
将采用自定义函数,允许您按照您想要命名的几乎任何顺序进行排序。
或者,捕获数组中的排序并使用 来提取输出顺序。
my %content_for;
my @ordered_id;
while ( <$input_filehandle> ) {
my ( $id, $content ) = split;
push ( @ordered_id, $id );
$content_for{$id} = $content;
}
print join ( "\n", @content_for{@ordered_id} ),"\n"
或者像Hash::Ordered
或Tie::IxHash
这样的有序哈希机制。
我在迭代方面提出了问题,但也许它不是对哈希的迭代,而是哈希构建过程是非确定性的。我可以设置一些初始化来以确定性和可复制的方式构建哈希吗?
没有。哈希不会那样工作。有关解释原因,请参阅 - perlsec
。随着更新版本的perl,它得到了更多随机,但它总是一个无序的数据结构。
你也许可以搞乱(如文章中提到的)PERL_HASH_SEED和PERL_PERTURB_KEYS,但这绝对不是一个好习惯。
PERL_HASH_SEED=0 ./somescript.pl
但是你应该记住,哈希排序仍然无法保证 - 密钥的排序可能仍会改变。尽管如此,它会比以前更加一致。这绝对不是在生产中使用的好东西,或者仅仅依赖于调试。
请注意:哈希种子是敏感信息。哈希是随机的,以防止针对Perl代码的本地和远程攻击。通过手动设置种子,可以部分或完全丧失此保护。