【问题标题】:Is Perl guaranteed to return consistently-ordered hash keys?Perl 是否保证返回一致排序的哈希键?
【发布时间】:2010-11-18 09:29:28
【问题描述】:

鉴于类似

foreach (keys %myHash) {
   ... do stuff ...
}

foreach (keys %myHash) {
   ... do more stuff ...
}

如果哈希没有改变,Perl 是否保证以一致的顺序迭代键?

【问题讨论】:

  • 只是出于好奇——你需要这个属性做什么?
  • 谁在投票否决一切?

标签: perl hash key


【解决方案1】:

Yes。来自perldoc -f keys

密钥以明显随机的顺序返回。实际的随机顺序可能会在 perl 的未来版本中发生变化,但保证与valueseach 函数产生的顺序相同(假设哈希尚未修改)强>。从 Perl 5.8.1 开始,出于安全原因,即使在 Perl 的不同运行之间,排序也是不同的(请参阅 perldoc perlsec 中的“算法复杂性攻击”)。

(强调我的)

【讨论】:

  • +1 如果人们至少尝试阅读 Perl 附带的优秀文档,那就太好了。
【解决方案2】:

编辑:

虽然普通哈希具有一致的顺序,但在 tied hash 的情况下,键的顺序定义不明确,因为它是用户控制的!


虽然哈希键顺序没有改变,但您可能应该重新考虑为什么需要这样做。

也许您可以一次处理哈希而不是两次?

您应该将哈希键保存到数组中作为防御性编程实践,除非数据的大小足够大以至于复制它会成为问题。作为奖励,您甚至可以轻松地对列表进行排序并以明确定义的顺序在哈希中进行处理。例如,

   my @keys = sort keys %myHash;

这避免了修改哈希的任何问题,因为除非您愿意,否则您的数组顺序永远不会改变。

如果你不这样做,你需要非常小心,不要做任何改变哈希的事情,否则元素的顺序会改变。查看Readonly 模块以确保该哈希值永远不会被修改。

【讨论】:

  • 我不明白 - 你为什么要对一个经过测试、记录并保证可以工作的功能保持警惕?这看起来就像使用文本编辑器并在一行中调用两次 File -> Safe 一样愚蠢,希望如果第一个静默失败,第二个会成功。
  • @moritz:问题不在于 Perl 改变了键顺序(或不改变),而是如果哈希被修改,顺序可以改变。这个答案暗示了一种防御性编程策略(单独的数组加上只读),用于将来维护 OP 的代码库,与 Perl 内部无关。
  • 除非有强大的性能理由不这样做,否则我总是尝试排序。经常被隐含地期望特定顺序的代码咬住,并在看似不相关的更改导致不同的键顺序时开始神秘地失败。
【解决方案3】:

这是一个相当冒险的期望。它可能会,但为什么要担心呢?提前获取键,保存结果,然后遍历保存的结果。然后,您可以保证以相同的顺序访问密钥。在未指定的实现细节的边缘工作是危险的。

编辑:错过了文档中的“保证”,但我仍然认为期望这永远不会改变是很危险的。尤其是当有更明智的方法可以达到同样的目的时。

【讨论】:

  • 为什么要在“保证”周围加引号? (a) 非常清楚地说明; (b) 不太可能改变,因为它对keysvalues 以相同的顺序返回很重要,这样当你不能使用each 时,两者就可以关联起来。
猜你喜欢
  • 2011-05-19
  • 1970-01-01
  • 2010-10-20
  • 1970-01-01
  • 2015-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多