我正在尝试实现一个自定义类,包括可比较的mixin。后来这个课用来做差异。该课程看起来像
class Element
include Comparable
attr_reader :name
def initialize(name)
@name = name
end
def <=>(other)
@name <=> other.name
end
end
现在一些测试值包含两个添加的条目与a相比。
a = Array.new
b = Array.new
a.push Element.new('y1')
a.push Element.new('y2')
a.push Element.new('y4')
a.push Element.new('x1')
a.push Element.new('x2')
a.push Element.new('x4')
b.push Element.new('y1')
b.push Element.new('y2')
b.push Element.new('y3')
b.push Element.new('y4')
b.push Element.new('x1')
b.push Element.new('x2')
b.push Element.new('x3')
b.push Element.new('x4')
现在在两个数组之间运行差异
puts Diff::LCS.diff(a, b).inspect
我希望现在有两个添加的对象,但它会找到8个更改...有什么想法吗?
[[["-", 2, #<Element:0x007fa9fb567898 @name="y4">],
["-", 3, #<Element:0x007fa9fbc69830 @name="x1">],
["-", 4, #<Element:0x007fa9fbca3378 @name="x2">],
["+", 2, #<Element:0x007fa9fb5e5e78 @name="y3">],
["+", 3, #<Element:0x007fa9fb606920 @name="y4">],
["+", 4, #<Element:0x007fa9fb625848 @name="x1">],
["+", 5, #<Element:0x007fa9fb647da8 @name="x2">],
["+", 6, #<Element:0x007fa9fbde8670 @name="x3">]]]
如果我们用
运行测试a = Array.new
b = Array.new
a.push 'y1'
a.push 'y2'
a.push 'y4'
a.push 'x1'
a.push 'x2'
a.push 'x4'
b.push 'y1'
b.push 'y2'
b.push 'y3'
b.push 'y4'
b.push 'x1'
b.push 'x2'
b.push 'x3'
b.push 'x4'
一切都按预期工作:
[[["+", 2, "y3"]],
[["+", 6, "x3"]]]
答案 0 :(得分:2)
从Diff::LCS
的来源检查,序列中的元素被用作散列键。
您编写的Element
类混合了Comparable模块,它在那里得到了==
方法。但是,它没有eql?
和hash
方法覆盖,Hash
用来确定密钥比较。
在Element
课程中,我们有
irb(main):013:0> a = Element.new("a")
=> #<Element:0x002ae4ce402da0 @name="a">
irb(main):014:0> b = Element.new("a")
=> #<Element:0x002ae4ce409ec0 @name="a">
irb(main):015:0> a == b
=> true
irb(main):016:0> a.eql? b
=> false
irb(main):017:0> a.hash == b.hash
=> false
irb(main):018:0> h = {}
=> {}
irb(main):019:0> h[a] = 1
=> 1
irb(main):020:0> h[b]
=> nil
这会影响LCS计算。
我认为修复是为eql?
类添加hash
和Element
方法。
class Element
include Comparable
attr_reader :name
def initialize(name)
@name = name
end
def <=>(other)
@name <=> other.name
end
def eql? other
other.class == Element and self.name == other.name
end
def hash
@name.hash ^ Element.hash
end
end