以正确的顺序哈希键和值

时间:2018-01-17 15:29:14

标签: perl hash

我已多次看到以下一段代码将哈希加入另一个哈希

%hash1 = ('one' => "uno");
%hash2 = ('two' => "dos", 'three' => "tres");

@hash1{keys %hash2} = values %hash2;

我认为每次"价值观"或者"键"函数被调用,它们的输出顺序是随机的。如果这是真的,那么上面的语句如何以正确的顺序获取双方的键和值?

换句话说,为什么没有机会得到两个' => ' TRES'合并两个哈希后在%hash1中? Perl是否足够聪明,知道如果"键"和"价值观"在相同的行上调用,然后键和值必须以相同的顺序给出?

2 个答案:

答案 0 :(得分:13)

请参阅this part of the docs

  

只要给定的散列未经修改,您就可以依赖键,值和每个散列重复返回相同的顺序。

答案 1 :(得分:5)

哈希是链表的数组。散列函数将密钥转换为一个数字,该数字用作存储值的数组元素(" bucket")的索引。多个密钥可以散列到同一个索引(" collision"),这是由链表处理的情况。

keysvalueseach使用的迭代器按照与哈希中的位置一致的顺序返回元素。我想它会遍历第一个存储桶中的链表,然后遍历第二个存储桶中的链表等。这些点是它不会随机化它在哈希元素上迭代的顺序。这就是为什么文档可以保证以下内容:

  

只要给定的散列未经修改,您就可以依赖键,值和每个散列重复返回相同的顺序。

什么是" random" [1] 是密钥将散列到的桶号。每个散列都有一个随机密码,扰乱散列函数。这导致散列中元素的顺序对于每个散列和程序的每次运行都是不同的。 [2]

向哈希添加元素会导致桶的数量增加,并且可能导致触发密码更改(如果其中一个链接列异常变长)。这两个都将改变该哈希中元素的顺序。

$ perl -le'
   my %h1 = map { $_ => 1 } "a".."j";
   my %h2 = map { $_ => 1 } "a".."j";
   print keys(%$_) for \%h1, \%h1, \%h2, \%h2;
'
hjfeadbigc
hjfeadbigc
bdgcifjhae
bdgcifjhae

$ perl -le'
   my %h1 = map { $_ => 1 } "a".."j";
   my %h2 = map { $_ => 1 } "a".."j";
   print keys(%$_) for \%h1, \%h1, \%h2, \%h2;
'
dcahigjbfe
dcahigjbfe
gihacdefbj
gihacdefbj
  1. 它并不是随机的。如果在哈希中插入两个元素,则第二个元素在第一个元素之后被迭代器返回的可能性大于50%。
  2. 在旧版本的Perl中,事情并非随意。