Closed tomasjura closed 4 years ago
Pasting code and return values from link mentioned in the description:
require 'diff/lcs'
class M
attr_reader :m
def initialize(m)
@m=m
end
def ==( o )
o.m == @m
end
def hash
@m.hash
end
def to_s
return @m.to_s
end
end
s1 = %w(ma be c e h j l m n po)
=> ["ma", "be", "c", "e", "h", "j", "l", "m", "n", "po"]
s2 = %w(ma be c d e f j k l m r s ta)
=> ["ma", "be", "c", "d", "e", "f", "j", "k", "l", "m", "r", "s", "ta"]
Diff::LCS::Internals.lcs(s1.map{ |s| M.new(s) } , s2.map { |s| M.new(s) })
=> [0, 1, 2]
Diff::LCS::Internals.lcs(s1, s2)
=> [0, 1, 2, 4, nil, 6, 8, 9]
Struck me as well.
This is because the hash is used to map the objects to their positions.
map
ping the strings to M
objects ends up by instantiating different objects for the same string, and different slots are allocated in index hash for these objects.
The custom class should redefine eql?
method to be an alias to ==
(in addition to custom ==
and hash
methods) so that equal objects will use the same slot in hash.
When comparing collection (Enumerable) of objects which are not Strings, then result is incorrect. See attached example.
lcs_test1.rb.txt