Ruby 1.8.6 Array#uniq 不删除重复的哈希值

2024-02-27

我在 ruby​​ 1.8.6 控制台中有这个数组:

arr = [{:foo => "bar"}, {:foo => "bar"}]

两个元素彼此相等:

arr[0] == arr[1]
=> true
#just in case there's some "==" vs "===" oddness...
arr[0] === arr[1]
=> true 

但是, arr.uniq 不会删除重复项:

arr.uniq
=> [{:foo=>"bar"}, {:foo=>"bar"}]

谁能告诉我这是怎么回事?

编辑:我可以写一个不是很聪明的唯一标识符,它使用include?如下:

uniqed = []
arr.each do |hash|
  unless uniqed.include?(hash)
    uniqed << hash
  end
end;false
uniqed
=> [{:foo=>"bar"}]

这会产生正确的结果,从而导致失败uniq更神秘了。

编辑2:一些关于正在发生的事情的注释,可能只是为了我自己的清晰起见。正如 @Ajedi32 在评论中指出的那样,统一化失败的原因是这两个元素是不同的对象。一些类定义eql? and hash用于比较的方法表示“这些实际上是同一件事,即使它们在内存中不是同一个对象”。例如,String 就是这样做的,这就是为什么您可以将两个变量定义为“foo”,并且它们彼此相等,即使它们不是同一个对象。

哈希类doesn't在 Ruby 1.8.6 中执行此操作,所以当.eql? and .hash在哈希对象上调用(.hash 方法与哈希数据类型无关 - 它就像哈希的校验和类型),它回退到使用 Object 基类中定义的方法,该方法只是说“它是内存中的同一个对象”。

The == and ===对于哈希对象,运算符已经做了我想要的事情,即如果两个哈希值的内容相同,则它们是相同的。我已经覆盖了Hash#eql?使用这些,像这样:

class Hash
  def eql?(other_hash)
    self == other_hash
  end
end

但是,我不知道如何处理Hash#hash:也就是说,我不知道如何生成一个校验和,对于内容相同的两个哈希值来说,该校验和是相同的,而对于具有不同内容的两个哈希值来说,该校验和总是不同的。

@Ajedi32 建议我看看 Rubinius 的实现Hash#hash方法在这里https://github.com/rubinius/rubinius/blob/master/core/hash.rb#L589 https://github.com/rubinius/rubinius/blob/master/core/hash.rb#L589,我的 Rubinius 实现版本如下所示:

class Hash
  def hash
    result = self.size
    self.each do |key,value|
      result ^= key.hash 
      result ^= value.hash 
    end
    return result
  end
end

这似乎确实有效,尽管我不知道“^=”运算符的作用,这让我有点紧张。而且,它非常慢——根据一些原始基准测试,大约慢了 50 倍。这可能会导致使用速度太慢。

编辑3:一些研究表明“^”是按位异或运算符。当我们有两个输入时,如果输入不同,则 XOR 返回 1(即,对于 0,0 和 1,1 返回 0,对于 0,1 和 1,0 返回 1)。

所以,一开始我以为这意味着

result ^= key.hash 

是简写

result = result ^ key.hash

换句话说,在 result 的当前值和其他值之间进行异或,然后将其保存在 result 中。但我仍然不太明白其中的逻辑。我认为 ^ 运算符可能与指针有关,因为在变量上调用它可以工作,而在变量的值上调用它则不起作用:例如

var = 1
=> 1
var ^= :foo
=> 14904
1 ^= :foo
SyntaxError: compile error
(irb):11: syntax error, unexpected tOP_ASGN, expecting $end

因此,在变量上调用 ^= 是可以的,但不是变量的值,这让我认为这与引用/取消引用有关。

后来的 Ruby 实现也有 Hash#hash 方法的 C 代码,而 Rubinius 的实现似乎太慢了。有点卡住了...


出于效率原因,Array#uniq不使用比较值==甚至===。根据the docs https://ruby-doc.org/core-2.4.2/Array.html#method-i-uniq:

它使用哈希值和 eql 来比较值?提高效率的方法。

(请注意,我在此处链接了 2.4.2 的文档。虽然 1.8.6 的文档不包含此声明,但我相信它对于该版本的 Ruby 仍然适用。)

在 Ruby 1.8.6 中,neither Hash#hash nor Hash#eql?已实施 https://ruby-doc.org/core-1.8.6/Hash.html,所以他们回退到使用Object#hash https://ruby-doc.org/core-1.8.6/Object.html#method-i-hash and Object#eql? https://ruby-doc.org/core-1.8.6/Object.html#method-i-eql-3F:

平等——在对象层面,==仅当 obj 和 other 是同一对象时才返回 true。通常,在后代类中重写此方法以提供特定于类的含义。

[...]

The eql?方法返回true如果 obj 和 anObject 具有相同的值。由 Hash 用于测试成员的相等性。对于 Object 类的对象,eql?是同义词==.

所以根据Array#uniq,这两个哈希是不同的对象,因此是唯一的。

要解决此问题,您可以尝试定义Hash#hash https://ruby-doc.org/core-2.4.2/Hash.html#method-i-hash and Hash#eql? https://ruby-doc.org/core-2.4.2/Hash.html#method-i-eql-3F你自己。如何执行此操作的详细信息留给读者作为练习。不过,您可能会发现它很有帮助,请参考Rubinius 对这些方法的实现 https://github.com/rubinius/rubinius/blob/master/core/hash.rb.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ruby 1.8.6 Array#uniq 不删除重复的哈希值 的相关文章

  • 在Ruby中从csv文件中获取第二行[重复]

    这个问题在这里已经有答案了 actual row File open file name 0 r first row data CSV foreach actual row do row first row data lt lt row 1
  • << 和 += 有什么区别?

    我一直在尝试使用数组 发现自己在理解以下代码时遇到了困难 first array second array third array I initialized 3 empty arrays third array lt lt 1 2 3 4
  • proc函数相对于方法有什么优点

    我正在解决一些问题欧拉计划 http projecteuler net 我提到我总是将短方法包装在 proc 函数中 我问自己 Why 答案是 我不知道 也许是因为它短 那么proc函数相对于普通方法除了短之外还有什么优点呢 Proc is
  • Javascript - 使数组索引 toLowerCase() 不起作用

    我试图将所有数组索引设置为小写字符串 但它不起作用 我在这里查看了其他答案并尝试了他们的解决方案 例如使用toString 添加之前toLowerCase但它不起作用 这很奇怪 我创建了一个问题的jsfiddlehere https jsf
  • SQL 更新数据集中的位置

    id1 id2 bool 1 1 F 1 2 F 2 1 F UPDATE table name SET bool T WHERE id1 id2 IN 1 1 2 1 Need work here 所以基本上我想选择条件为 id1 id2
  • 载波无法删除图像

    我现在使用 Carrierwave 上传图像 一切都很好 除了一个 当我添加用于删除上传图像的复选框时 我收到错误 无法批量分配受保护的属性 remove image Form Model class Manufacturer lt Act
  • 解码Json数据数组并插入到mysql

    这个问题可能已经在这里问过 但我尝试搜索找不到它 我有如下 Json 数据 CityInfo CityCode 5599 Name DRUSKININKAI CityCode 2003 Name KAUNAS CityCode 2573 N
  • 为什么 char 数组需要 strcpy 而 char star 不需要 - 在 C 中使用结构

    我对这段代码有一个误解 typedef struct EXP int x char name char lastName 40 XMP main XMP a a name eaaa a lastName strcpy a lastName
  • 在 Node.js 中创建 JSON 数组

    我需要在用 Node js 编写的服务器中创建一个 JSON 字符串 以便在请求时发送到客户端 问题是这个 JSON 取决于服务器中的可用数据 因此 JSON 数组的大小并不总是相同 我已经尝试了一整天 但尽管我感觉很接近 但我仍然不明白
  • 奇怪的java字符串数组空指针异常[重复]

    这个问题在这里已经有答案了 这个问题是在实践测试中出现的 创建一个新的字符串数组 将其初始化为空 然后初始化第一个元素并打印它 为什么会出现空指针异常呢 为什么它不打印 一 这与字符串不变性有关吗 public static void ma
  • 过滤任何属性包含值的对象数组

    我想知道根据字符串关键字过滤对象数组的最干净 更好的方法是什么 必须在对象的任何属性中进行搜索 当我打字时lea我想遍历所有对象及其所有属性以返回包含的对象lea 当我打字时italy我想遍历所有对象及其所有属性以返回包含的对象italy
  • 未签出...捆绑安装无法修复帮助!

    https github com intridea omniauth git at master is not checked out Please run bundle install Bundler GitError 那我该怎么办 捆绑
  • Numpy:生成二维高斯 pdf 总和作为数组

    我正在尝试生成一个 600 x 600 numpy 数组 其中包含 10 个类似高斯数组的总和 每个数组都有一个随机生成的中心 我尝试使用高斯滤波器来生成各个类似高斯的数组 然后将它们相加 但我确信有一种矢量化的方法可以解决这个问题 即使n
  • Lua表在内存中是如何处理的?

    lua如何处理表的增长 是否相当于ArrayList在Java中 IE 需要连续的内存空间 并且当它变得大于已经分配的空间时 内部数组被复制到另一个内存空间 有什么聪明的方法来引导吗 我的问题是 表是如何存储在内存中的 我不是问如何在 Lu
  • 有没有一种好方法来计算 ruby​​ 中范围元素的总和

    计算范围总和的好方法是什么 Input 4 10 Output 4 5 6 7 8 9 10 49 您可以使用EnumerableRange 对象上的方法 在本例中使用Enumerable inject 4 10 inject gt 49
  • ruby 1.9.1 的 gem install mongrel 失败

    昨天我开始了 Rails 开发 我安装了 ruby 1 9 1 rubygems 和 Rails 跑步gem install mongrel工作得很好 表面上也安装了杂种 我有点困惑 因为 script server 默认启动 webric
  • 在 Rails 中强制内联渲染 PDF 文档

    我正在编写一个从一组 XML 文件生成 PDF 文件的服务 正在正确生成 PDF 但是 每次我单击 查看 PDF 链接时 浏览器都会要求用户下载 PDF 文件 我需要 PDF 内联显示 就像任何常规 HTML 页面一样 我虽然我写的代码是正
  • 对 Rails 3.1 中的特定路由强制使用 SSL

    我需要强制启用 SSL所有路线在我的申请中除了landing index In config application rb 我有 config force ssl true Then in landing controller rb 我有
  • 选择MySql表数据放入数组中

    我尝试从 mysql 捕获数据并将它们全部放入数组中 认为 users table id name code 1 gorge 2132 2 flix ksd02 3 jasmen skaod2 sql mysql query select
  • 有没有办法让 Ruby 临时文件永久存在?

    如果我通过创建了一个临时文件Tempfile 除了将其复制到另一个文件之外 还有什么方法可以使其 永久 吗 我想避免它在关联时被删除Tempfile实例被垃圾收集或进程被终止 在相关的一点上 有没有办法利用Tempfile机制 或使用类似的

随机推荐

  • 在 Excel/VBA 中将文本框附加到图表上的点或线

    我想知道如何将文本框附加到我正在处理的宏的 Excel 图表中的点或线 我一直在使用 AddTextbox方法如 Shapes AddTextbox msoTextOrientationHorizontal 150 250 100 15 T
  • 从位图图像列表创建 .avi 文件

    我目前正在尝试制作一个屏幕录像机 我制作了位图图像列表 并希望将它们放入 avi 文件中 无论如何 在 C 中可以做到这一点吗 注意 我是新手 所以保持简单 Try SharpAvi http sharpavi codeplex com图书
  • openCV 243 使用静态库错误 LNK2019

    我正在尝试在 64 位 vs 10 控制台应用程序中使用 openCV 243 静态库 我的操作系统是win7 64位 我已经包含以下库 pragma comment lib final test libs staticlib opencv
  • mac os Sierra 上的 Gitx:不再支持 Objective-C 垃圾回收

    升级到 Sierra 10 12 后 我在 GitX 中遇到垃圾收集问题 objc 2253 Objective C garbage collection is no longer supported 我四处寻找 发现这个 gix 叉子似乎
  • 循环遍历 MS Project 的每个字段

    我试图循环遍历我的 MS Project 文件中的每个字段并收集有关该字段的信息 自定义名称是特定的 做到这一点最简单的方法是什么 Thanks 要获取字段的自定义名称 您需要字段常量并循环遍历所有字段 您需要存储所有字段常量的列表 htt
  • 使用 spring StoredProcedure 插入 oracle clob IN 参数时克服 32k 限制

    环境 oracle 11g spring jdbc 3 2 2 RELEASE jar JDK 1 7 Oracle UCP 驱动程序 我有一个存储过程 它将记录插入到具有 CLOB 列的表中 SP 在其他 IN 和 OUT 参数中具有 C
  • Rails RSpec 中未定义的方法“create”

    我已经安装了 FactoryBot 并尝试将其与 RSpec 一起使用 scenario User signs in do create user email email protected cdn cgi l email protecti
  • python 异步http请求

    我正在尝试在 python 中使用 twitter 搜索网络服务 我想调用一个网络服务 例如 http search twitter com search json q blue 20angels rpp 5 include entitie
  • ttf 文件无法在 Chrome 和 Firefox 上呈现

    我一直在尝试在 Chrome 和 Firefox 中渲染 ttf 文件 但它似乎不起作用 渲染 woff 文件时工作正常 我从以下网站下载了该合集http www google com webfonts UsePlace use Colle
  • Debug.WriteLine 锁

    我的程序经常因死锁而停止 当我进行全部破坏并查看线程时 我发现三个线程卡在我们的日志记录函数中 public class Logging public static void WriteClientLog LogLevel logLevel
  • 识别 UITapGestureRecogniser 的多个 UILabels 点击

    在我的视图加载中 我有两个 UILabel 并且我为两者添加了相同的 tapGesture 如果点击特定标签 则应该执行其功能 但我无法这样做 void viewDidLoad lblEditProfile userInteractionE
  • 如何找到此特定字符串的多次出现并将它们分成一个列表?

    我试图在更大的整个字符串中找到特定的一段字符串 这是字符串 粗体字是我想使用 python re 库中的 re findall 函数提取的字符串 文本 p1 1 SNtestfilefri01 天线系统 文本 p1 2 SNtestfile
  • 创建一个对于读取操作来说线程安全的 DOM

    我的应用程序从多个 xml 源组成一个网页模型 这些源被正常的 Xerces 解析器解析为 DOM 对象到内存中 不幸的是 Xerces DOM 对象是not对于只读操作是线程安全的 我希望能够重用解析后的 DOM 进行读取 有谁知道我使用
  • 如何隐藏代码并重新运行 jupyter 笔记本中的所有单元格?

    我想在 Jupyter Notebook 的开头添加某种功能 隐藏 显示所有单元格并重新运行所有单元格 我最终想要得到的是一组图表 当所有单元格重新运行时 这些图表都会刷新 详细信息和我尝试过的 帖子IPython 从小部件运行下面的所有单
  • 更改 ggplot2 中栅格图的颜色

    由于一些不相关的原因 我尝试使用 ggplot2 而不是栅格包绘图函数来制作栅格图 我想缩放颜色 使图上的最低温度为蓝色 图上的最高温度为红色 而中间范围为白色 我已经尝试了 ggplot2 中的许多功能 但始终未能获得所需的结果 这就是我
  • 在 doxygen 中使用模块组内的节

    我寻求构建 doxygen 模块组内容的首选方法 例如 我想在不同部分的以下模块组中构造 details 文本 特别是每个部分都应该出现在生成的 PDF 的书签中 作为模块组的子元素 defgroup lorem brief Lorem i
  • 如何访问 Django Rest Framework 3.0 序列化程序中的查询参数?

    例如 在 Django Rest Framework 2 x 中 您可以访问序列化器中的 fields 查询参数 如下所示 fields self context request QUERY PARAMS get fields 这在 DRF
  • 如何针对 SharePoint 网站中的任何更改创建每日摘要警报

    我最近收到一个要求 要求某人接收有关 SharePoint 网站内任何更改的每日摘要警报 每个网站都有一个负责其网站内容的所有者 目前我们的工作方式是为站点内的每个列表 库自动设置警报 Get the Lists on this Site
  • PHP 有损/无损压缩图像

    我如何使用 PHP 以有损 无损压缩的方式压缩图像 就像这两个网站压缩图像一样 https compressor io https compressor io and https kraken io web interface https
  • Ruby 1.8.6 Array#uniq 不删除重复的哈希值

    我在 ruby 1 8 6 控制台中有这个数组 arr foo gt bar foo gt bar 两个元素彼此相等 arr 0 arr 1 gt true just in case there s some vs oddness arr