我想使用相同的键构建几个哈希,并且在打印它们时键的顺序相同。因此,在下面的示例中,$hash1
和$hash2
的键应该总是具有相同的顺序,但是在创建哈希时不需要保持该顺序。
use Data::Dumper;
my $hash1 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
my $hash2 = {
keyc => 2,
key1 => 1,
keya => 3,
keyb => 4,
};
print Dumper $hash1, $hash2;
但输出如下:
$VAR1 = {
'key1' => 1,
'keyc' => 2,
'keyb' => 4,
'keya' => 3
};
$VAR2 = {
'keyb' => 4,
'keya' => 3,
'keyc' => 2,
'key1' => 1
};
- 即 * 散列有一个不同的和意外的顺序。我的perl有什么问题?
我的Perl版本是:
This is perl 5, version 18, subversion 2 (v5.18.2) built for darwin-thread-multi-2level
(with 2 registered patches, see perl -V for more detail)
注意事项:我知道perl hash的键是无序的,我希望它们有相同的顺序,但不需要有排序的顺序。我希望如果我再次运行代码,我可以得到相同的打印输出。
根据answers的建议,我设置了两个环境变量:PERL_HASH_SEED=0x00 PERL_PERTURB_KEYS=0
然后我可以得到相同的输出,当我重复运行代码。
3条答案
按热度按时间fsi0uk1n1#
当打印一个散列时,有几个不同的顺序概念是相关的:“插入顺序”,“排序顺序”和“随机”。请参阅
perlrun
文档的环境部分,了解如何控制这种行为,以及为什么默认使用散列随机化。至少有十年的时间,perl中的散列不能保证键的顺序。最近,散列随机化已经成为一般安全性“强化”工作的一部分。散列随机化有很好的理由。有关详细信息,请参阅
perlsec
关于算法复杂性攻击的讨论。您将在Perl安全文档中注意到,perl-5.18
中添加了进一步的增强功能-如果你看到一个不同的行为相比,以前的版本,这可能是由于这些最新的变化。除了以确定性的方式显式地使用sorting your hash keys之外,还有其他方法可以用来对散列进行排序:
Hash::Ordered
就是一个例子。Hash::Ordered
文档很好地讨论了许多其他模块的优缺点。而哈希是一个“* 无序篮子 ”的标量安排在键-值对;数组 * 是标量的“ 有序序列 *”[1]。“切片”是访问“列表,数组,切片使用
@
符号,因为该操作返回多个值的列表-使用@
,我们得到“其结果是,一种对散列施加某种“顺序”的方法是使用切片来访问它:我们想要的是“
zxy
“而不是“zyx
“。为了在这个哈希上强加我们任意版本的顺序,我们首先需要认识到罪魁祸首是keys %hashed
,它以随机顺序返回密钥。解决方案是ccurse的sort
密钥,在这个人为的例子中,我们将它们存储在@sort_order
中,并用它从哈希中“切片”出我们想要的内容,我们想要的方式:Tada!!当你想在散列中存储键和值,但以有序的方式访问该数据时,切片可能很有用。当你想对散列进行切片时,请记住“
@
“;正如perldata
所说:“你在散列切片上使用'@'
......[因为]你得到的是......一个列表”。列表是有序的。[1]散列的定义是“无序篮子”,数组的定义是“有序序列”,这些定义来自Mike Friedman(FRIEDO)关于Arrays vs. Lists in Perl的优秀文章。
更多参考资料
perlfaq
-q如何始终保持哈希排序?vltsax252#
你的perl没什么问题,散列没有排序。
如果你想按键排序,你需要做这样的事情:
对于hash2也是一样。
klsxnrf13#
G. Cito的回答是正确的。但是,如果你想从Data::Dumper得到排序的输出,你可以这样做: