为什么 ruby .hash 每次都会产生不同的输出

  • 本文关键字:输出 ruby hash ruby hash
  • 更新时间 :
  • 英文 :


如果我多次运行以下单行 ruby 脚本,它每次都会产生不同的输出值。

puts "This is a string".hash

这是怎么回事?我应该如何更改它以从任何给定输入字符串的 .hash 中获取一致的、可重现的值?

编辑:"可能的重复"建议其他哈希方法。我正在尝试重现另一个我无法控制的脚本的行为,该脚本使用 .hash 并获得一致的结果。更改哈希方法不是一种选择。

编辑#2:如下面的另一条评论所述,我要重现其行为的另一个脚本位于.exe包装器中。它的历史可以追溯到 2006 年,这意味着 Ruby 版本必须是 1.8.5 或更早版本。#hash 方法在早期版本的 Ruby 中的工作方式是否不同,如果是这样,是否有人生成了复制这些早期版本行为的脚本?(它可以是不同的名称。

这是

怎么回事?

程序的生存期内,不同对象的#hash应该不同,而相同对象的应该相同。绝对不能保证程序的不同调用的值是什么。

这里的文档非常明确(粗体强调我的(:

对象的哈希值在 Ruby 的调用或实现中可能不相同。如果您需要跨 Ruby 调用和实现的稳定标识符,则需要使用自定义方法生成一个

[注意:由于某种原因,当前版本的 Ruby 的文档无法在 ruby-doc.org 上正确呈现。不过,它在当前的主分支中是相同的。

我应该如何更改它以从任何给定输入字符串的 .hash 中获取一致的、可重现的值?

不使用它。

>我认为了解#hash的用途可能会有所帮助它用于将 Ruby 对象存储到Hash数据结构的特定存储桶中 - 或者,将其包含在Set中 - 但这是一个实现细节,因为 Ruby 集是在哈希的"之上"实现的。它不用于消化值。一旦你知道这一点,很明显#hash不应该满足以下约束:

  • 尽量减少冲突 -有时发生冲突是可以的,因为如果有多个项目,哈希中的存储桶可能会回归到搜索中
  • 虚拟机的整个生命周期内保持稳定 - 不是必需的,因为每次都会重新"重建"哈希,即使您进行封送处理也是如此

它应满足以下约束

  • 在虚拟机的相同生存期内稳定 - 否则项目可能必须"迁移"到 Hash 中的其他存储桶,这是不可能实现的。这就是为什么字符串在用作哈希键时会被冻结的原因
  • 快速计算
  • 适合Ruby Hash桶使用的任意"密钥大小"(在MRI中,我相信它是st_index_t的大小(

第二个要求可以通过多种方式满足。例如,可以通过使用更快的哈希函数来满足它。但它也可以通过查找"任意"计算的哈希值来满足,例如字符串,如果这个特定的字符串是另一个字符串的副本 - 通过重用该值。另一种方法(有时也应用(是从 Ruby 对象 ID 派生哈希值 - 根据定义,哈希值在虚拟机运行中会发生变化。

Jörg 确实如此 - 就您的目的而言,hash(( 函数不太合适,因为它是为不同的用例制作的。不过,还有大量的替代方案 - 通常的SHA,杂音哈希,xxhash等 - 可以满足您的要求并保证是内容派生的。

最新更新