以正确的顺序散列键和值

Posted

技术标签:

【中文标题】以正确的顺序散列键和值【英文标题】:Hash keys and values in the right order 【发布时间】:2018-06-26 12:58:18 【问题描述】:

我已经多次看到下面这段代码将一个哈希连接到另一个哈希

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

@hash1keys %hash2 = values %hash2;

我认为每次调用“values”或“keys”函数时,它们的输出顺序都是随机的。如果是这样,上面的语句如何在两边以正确的顺序获取键和值?

换句话说,为什么在合并两个哈希后没有机会在 %hash1 中获得 'two' => 'tres'? Perl 是否足够聪明,知道如果在同一行调用“键”和“值”,那么键和值必须以相同的顺序给出?

【问题讨论】:

简化:哈希算法的工作方式是在程序的相同执行期间,给定哈希中的项目的顺序是随机的,但保证相同。如果数据结构发生变化,顺序可能会发生变化。第二次调用程序时,不保证是一样的。 【参考方案1】:

见perldoc -f keys

只要未修改给定的哈希值,您就可以依赖键、值和每一个重复返回彼此相同的顺序。

【讨论】:

【参考方案2】:

哈希是一个链表数组。散列函数将键转换为一个数字,该数字用作存储值的数组元素(“桶”)的索引。多个键可以散列到同一个索引(“冲突”),这种情况由链表处理。

keysvalueseach 使用的迭代器以与它们在哈希中的位置一致的顺序返回元素。我想它会遍历第一个桶中的链表,然后遍历第二个桶中的链表,等等。关键是它不会随机化它遍历散列元素的顺序。这就是文档保证以下内容的原因:

只要未修改给定的哈希值,您就可以依赖键、值和每一个重复返回彼此相同的顺序。

什么是“随机”[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

    这不是完全随机的。如果在哈希中插入两个元素,则迭代器在第一个元素之后返回第二个元素的几率超过 50%。 在旧版本的 Perl 中,事情并不那么随机。

【讨论】:

以上是关于以正确的顺序散列键和值的主要内容,如果未能解决你的问题,请参考以下文章

从数组 ruby​​ 生成哈希键和值

从 LinkedHashMap 对象返回键和值的顺序是不是得到保证?

在python中的字典中切换键和值[重复]

从 OrderedDict 中删除键和值

字典键和值以分隔 numpy 数组

解析 HTML 以获取键和值