artist versions: refactor diffs.
This commit is contained in:
35
app/logical/set_diff.rb
Normal file
35
app/logical/set_diff.rb
Normal file
@@ -0,0 +1,35 @@
|
||||
class SetDiff
|
||||
attr_reader :added, :removed, :obsolete_added, :obsolete_removed, :changed, :unchanged
|
||||
|
||||
def initialize(new, old, latest)
|
||||
new, old, latest = new.to_a, old.to_a, latest.to_a
|
||||
|
||||
@added, @removed, @changed = changes(new, old)
|
||||
@unchanged = new & old
|
||||
@obsolete_added = added - latest
|
||||
@obsolete_removed = removed & latest
|
||||
end
|
||||
|
||||
def changes(new, old)
|
||||
added = new - old
|
||||
removed = old - new
|
||||
changed = []
|
||||
|
||||
removed.each do |removal|
|
||||
if addition = find_similar(removal, added)
|
||||
changed << [removal, addition]
|
||||
added -= [addition]
|
||||
removed -= [removal]
|
||||
end
|
||||
end
|
||||
|
||||
[added, removed, changed]
|
||||
end
|
||||
|
||||
def find_similar(string, candidates, max_dissimilarity: 0.75)
|
||||
distance = ->(other) { DidYouMean::Levenshtein.distance(string, other) }
|
||||
max_distance = string.size * max_dissimilarity
|
||||
|
||||
candidates.select { |candidate| distance[candidate] <= max_distance }.sort_by(&distance).first
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user