ruby - Own class with spaceship operator does not work for LCS Diff -
i'm trying implement custom class including comparable mixin. later class used diff. class looks like
class element include comparable attr_reader :name def initialize(name) @name = name end def <=>(other) @name <=> other.name end end now test values 2 added entries compared 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') and run diff between both arrays
puts diff::lcs.diff(a, b).inspect i expect 2 added objects finds 8 changes... ideas why?
[[["-", 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">]]] if run test with
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' everything works expected:
[[["+", 2, "y3"]], [["+", 6, "x3"]]]
inspecting source of diff::lcs, elements in sequences used hash key.
the element class wrote mixed comparable module, got == method there. however, doesn't have eql? , hash method override, used hash determine key comparison.
with element class, have
irb(main):013:0> = element.new("a") => #<element:0x002ae4ce402da0 @name="a"> irb(main):014:0> b = element.new("a") => #<element:0x002ae4ce409ec0 @name="a"> irb(main):015:0> == 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 this affects lcs calculation.
the fix add eql? , hash method element class, think.
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 , self.name == other.name end def hash @name.hash ^ element.hash end end
Comments
Post a Comment