From 7d9eb5bcddf4932e62285d732b48fe29702b8135 Mon Sep 17 00:00:00 2001 From: Jacob Elder Date: Wed, 27 Apr 2016 10:16:30 -0400 Subject: [PATCH 1/3] Clean up CodeClimate minor warnings --- lib/dyph/two_way_differs/output_converter.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/dyph/two_way_differs/output_converter.rb b/lib/dyph/two_way_differs/output_converter.rb index 26c4b15..d53e8c4 100644 --- a/lib/dyph/two_way_differs/output_converter.rb +++ b/lib/dyph/two_way_differs/output_converter.rb @@ -1,3 +1,4 @@ +# rubocop:disable Metrics/AbcSize module Dyph module TwoWayDiffers # rubocop:disable Metrics/ModuleLength From 011a358cb5fd9d49c65fc8d1943d32caf51dbdd1 Mon Sep 17 00:00:00 2001 From: Jacob Elder Date: Wed, 27 Apr 2016 11:00:17 -0400 Subject: [PATCH 2/3] Extract Dyph3.min_diff monkeypatch from www --- dyph.gemspec | 1 + lib/dyph.rb | 2 + lib/dyph/min_diff.rb | 76 ++++++++++++++++++++++++++++++++++ spec/lib/dyph/min_diff_spec.rb | 13 ++++++ spec/spec_helper.rb | 7 ++-- 5 files changed, 96 insertions(+), 3 deletions(-) create mode 100644 lib/dyph/min_diff.rb create mode 100644 spec/lib/dyph/min_diff_spec.rb diff --git a/dyph.gemspec b/dyph.gemspec index 19fb99c..dcc6fc1 100644 --- a/dyph.gemspec +++ b/dyph.gemspec @@ -22,6 +22,7 @@ Gem::Specification.new do |spec| spec.add_development_dependency "pry-rescue" spec.add_development_dependency "pry-stack_explorer" spec.add_development_dependency 'rspec', '~> 3.3.0' + spec.add_development_dependency 'rspec-its', '~> 1.2.0' spec.add_development_dependency "awesome_print" spec.add_development_dependency "factory_girl" spec.add_development_dependency "codeclimate-test-reporter" diff --git a/lib/dyph.rb b/lib/dyph.rb index 5ff7952..c7f6dcd 100644 --- a/lib/dyph.rb +++ b/lib/dyph.rb @@ -1,6 +1,8 @@ require "dyph/version" require "dyph/differ" +require "dyph/min_diff" + require "dyph/merge_result" require "dyph/outcome" diff --git a/lib/dyph/min_diff.rb b/lib/dyph/min_diff.rb new file mode 100644 index 0000000..6f9d62c --- /dev/null +++ b/lib/dyph/min_diff.rb @@ -0,0 +1,76 @@ +module Dyph + + # Perform a two-way diff of the given arrays twice, the second time with left and right reversed, and return the smaller result. + # @param left [Object] + # @param base [Object] + # @return [MergeResult] + def self.min_diff(left, right) + a = Differ.two_way_diff(left, right) + b = Differ.two_way_diff(right, left) + if a.size <= b.size + a + else + sort_actions(invert_actions(b)) + end + end + + # Invert the meanings of deleted and added chunks. + # @param actions [object] + # @return actions [object] + def self.invert_actions(actions) + actions.map do |action| + case action + when Action::Add then Action::Delete.new(value: action.value, old_index: action.old_index, new_index: action.new_index) + when Action::Delete then Action::Add.new(value: action.value, old_index: action.old_index, new_index: action.new_index) + else action + end + end + end + + # Reorder a diff result so that deletes are always before adds. + # @param actions [object] + # @return actions [object] + def self.sort_actions(actions) + actions = actions.reduce([]) do |result, action| + case action + when Action::Delete, Action::Add + ChangeGroup.begin(result) + result.last.add action + when Action::NoChange + ChangeGroup.end(result) + result << action + end + result + end + ChangeGroup.end(actions) + return actions + end + + class ChangeGroup + + def initialize + @adds = [] + @deletes = [] + end + + def add(change) + case change + when Action::Delete then @deletes << change + when Action::Add then @adds << change + end + end + + def values + [*@deletes, *@adds] + end + + def self.begin(action) + action << new unless action.last.is_a? self + end + + def self.end(action) + action.concat(action.pop.values) if action.last.is_a? self + end + end + +end diff --git a/spec/lib/dyph/min_diff_spec.rb b/spec/lib/dyph/min_diff_spec.rb new file mode 100644 index 0000000..4c56bc3 --- /dev/null +++ b/spec/lib/dyph/min_diff_spec.rb @@ -0,0 +1,13 @@ +require 'spec_helper' + +describe Dyph do + describe ".min_diff" do + let(:left) { %w[a b c d e f g] } + let(:right) { %w[d e f g a b c] } + let(:regular_diff) { Dyph::Differ.two_way_diff(left, right) } + let(:subject) { Dyph.min_diff(left, right) } + + its(:length) { is_expected.to be < regular_diff.length } + + end +end \ No newline at end of file diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index e0b4fb2..ded99db 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,12 +1,13 @@ require "codeclimate-test-reporter" CodeClimate::TestReporter.start -require 'dyph' +require "dyph" require "pry" require "awesome_print" -require 'codeclimate-test-reporter' -require 'faker' +require "codeclimate-test-reporter" +require "faker" +require "rspec/its" Dir[File.dirname(__FILE__) + '/fixtures/*.rb'].each {|file| require file } From 093305949f29caa1dc3401653a6a6e65ec558920 Mon Sep 17 00:00:00 2001 From: Jacob Elder Date: Wed, 27 Apr 2016 17:39:09 -0400 Subject: [PATCH 3/3] Remove errant rubocop declaration --- lib/dyph/two_way_differs/output_converter.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/dyph/two_way_differs/output_converter.rb b/lib/dyph/two_way_differs/output_converter.rb index d53e8c4..bd7ab04 100644 --- a/lib/dyph/two_way_differs/output_converter.rb +++ b/lib/dyph/two_way_differs/output_converter.rb @@ -1,4 +1,3 @@ -# rubocop:disable Metrics/AbcSize module Dyph module TwoWayDiffers # rubocop:disable Metrics/ModuleLength @@ -177,4 +176,4 @@ def partition_into_actions(array) end end end -end \ No newline at end of file +end