提问人:Lars Schirrmeister 提问时间:9/28/2023 更新时间:9/28/2023 访问量:80
Array 上的 Ruby #union 的反应非常奇怪
Ruby #union on Array reacts very strangely
问:
我喜欢使用 Array#union 或 #|方法返回删除重复项的对象数组。我在我的类上有一个自定义实现。
如果我这样做,就会有一种非常奇怪的行为。最多 8 个元素,联合工作正常,但对于更多元素,重复项不会被删除。这实际上是 ruby 的错误还是我错过了什么?eql?
class A
attr_accessor :name
def initialize(name)
self.name = name
end
def eql?(other)
other.name.eql?(name)
end
end
as = names.map { |name| A.new(name) }
bs = names.map { |name| A.new(name) }
as | bs
=>
[#<A:0x00007fe503692388 @name="a">,
#<A:0x00007fe503692310 @name="b">,
#<A:0x00007fe5036922e8 @name="c">,
#<A:0x00007fe5036922c0 @name="d">,
#<A:0x00007fe503692298 @name="e">,
#<A:0x00007fe503692270 @name="f">,
#<A:0x00007fe503692248 @name="g">,
#<A:0x00007fe503692220 @name="h">,
#<A:0x00007fe5036921f8 @name="i">,
#<A:0x00007fe5036921d0 @name="j">,
#<A:0x00007fe5036921a8 @name="k">,
#<A:0x00007fe503692180 @name="l">,
#<A:0x00007fe5035732e0 @name="a">,
#<A:0x00007fe5035732b8 @name="b">,
#<A:0x00007fe503573290 @name="c">,
#<A:0x00007fe503573268 @name="d">,
#<A:0x00007fe503573240 @name="e">,
#<A:0x00007fe503573218 @name="f">,
#<A:0x00007fe5035731f0 @name="g">,
#<A:0x00007fe5035731c8 @name="h">,
#<A:0x00007fe5035731a0 @name="i">,
#<A:0x00007fe503573178 @name="j">,
#<A:0x00007fe503573150 @name="k">,
#<A:0x00007fe503573128 @name="l">]
as[0..7] | bs[0..7]
=>
[#<A:0x00007fe503692388 @name="a">,
#<A:0x00007fe503692310 @name="b">,
#<A:0x00007fe5036922e8 @name="c">,
#<A:0x00007fe5036922c0 @name="d">,
#<A:0x00007fe503692298 @name="e">,
#<A:0x00007fe503692270 @name="f">,
#<A:0x00007fe503692248 @name="g">,
#<A:0x00007fe503692220 @name="h">]
答:
6赞
Tjad Clark
9/28/2023
#1
您需要根据 @engineersmnky 关于 Object#eql? 的注释实现这两个 和方法,该注释期望实例哈希值相同eql?
hash
eql?
class A
attr_accessor :name
def initialize(name)
@name = name
end
def eql?(other)
other.name.eql?(@name)
end
def hash
[@name].hash
end
end
#declare inclusive range from 'a' to 'm'
names = 'a'..'m'
as = names.map { |name| A.new(name) }
bs = names.map { |name| A.new(name) }
as | bs
输出:
[#<A:0x0000558a74860020 @name="a">,
#<A:0x0000558a7485bf98 @name="b">,
#<A:0x0000558a7485bf70 @name="c">,
#<A:0x0000558a7485bf48 @name="d">,
#<A:0x0000558a7485bf20 @name="e">,
#<A:0x0000558a7485bef8 @name="f">,
#<A:0x0000558a7485bed0 @name="g">,
#<A:0x0000558a7485bea8 @name="h">,
#<A:0x0000558a7485bd90 @name="i">,
#<A:0x0000558a7485bd40 @name="j">,
#<A:0x0000558a7485bd18 @name="k">,
#<A:0x0000558a7485bcf0 @name="l">,
#<A:0x0000558a7485bcc8 @name="m">]
评论
0赞
Lars Schirrmeister
9/28/2023
谢谢。这很有帮助。那么,您是否同意这里的文档有点误导?ruby-doc.org/core-3.0.0/Array.html#method-i-7C
0赞
Tjad Clark
9/28/2023
是的,我认为它丢失了 - 从旧版本开始,文档用于呈现
4赞
engineersmnky
9/28/2023
@LarsSchirrmeister 我不确定误导是否正确。如果你看一下 Object#eql? 的文档,它确实指出:“对于任何一对对象,其中 eql?
返回 true
,则两个对象的哈希
值必须相等。因此,任何覆盖 eql?
的子类也应该适当地覆盖哈希
。我认为这是记录这一点的合适地方,因此(工会)只需说明“使用”比较项目“似乎就足够了Array#|
eql?
1赞
Lars Schirrmeister
9/29/2023
哦,好吧。我不知道。是的,你是对的,那么一切都很好。谢谢@engineersmnky
3赞
steenslag
9/30/2023
A = Struct.new(:name)
为您提供与 Class 相同的行为(它附带了 和 )。initialize
eql?
hash
评论