simplediff-ruby 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (5) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +39 -0
  3. data/lib/simplediff-ruby.rb +63 -0
  4. data/test/test.rb +125 -0
  5. metadata +78 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 828b2453c0f2dc00a611c3db384401a97f743e42
4
+ data.tar.gz: 4ad216cdfefe86ded7e46bde4d6050f9b703800d
5
+ SHA512:
6
+ metadata.gz: e392f127f0e96620191b8d6263bea380a2e591bc1b419f0c5093feba24e209266a6841d507d1efa7070db05f67825a21a9c998a8eb01d33495636368fbbce473
7
+ data.tar.gz: 6dd464e0bb9235dd66a0ba4ca787ac1b783d87f4a170e17a4a01fa83a6754f907d521e86848edbd791ba5022ce775d3effb70d0db261a289722bbbae78c62825
@@ -0,0 +1,39 @@
1
+
2
+ SimpleDiff Ruby 1.0
3
+ ==============
4
+
5
+ **simplediff-ruby** is a Ruby gem implementation of the [simplediff](https://github.com/paulgb/simplediff) algorithm. It finds the difference between two arrays of strings, numbers, hashes, or arrays.
6
+
7
+ Use
8
+ ----
9
+
10
+ `require` the gem to expose the `SimpleDiff` class.
11
+
12
+ require "simplediff-ruby"
13
+
14
+ Then call `SimpleDiff.compare` to find the diffs.
15
+
16
+ source = ['The', 'quick', 'brown', 'fox']
17
+ target = ['The', 'slow', 'green', 'turtle']
18
+ SimpleDiff.compare(source, target)
19
+
20
+ The output will be an array of hashes representing the differences between the compared arrays.
21
+
22
+ [
23
+ { change: '=', content: ['The'] },
24
+ { change: '-', content: ['quick', 'brown', 'fox'] },
25
+ { change: '+', content: ['slow', 'green', 'turtle'] }
26
+ ]
27
+
28
+ Test
29
+ ----
30
+
31
+ Use `ruby test/test.rb` to run the test cases.
32
+
33
+ $ ruby test/test.rb
34
+
35
+ License
36
+ -------
37
+
38
+ SimpleDiff Ruby is available under a zlib/libpng
39
+ license. See the provided `LICENSE` file for more details.
@@ -0,0 +1,63 @@
1
+ class SimpleDiff
2
+ # Diffing algorithm taken from - https://github.com/paulgb/simplediff
3
+ def self.compare(source, target)
4
+ source ||= []
5
+ target ||= []
6
+ max = si_start = ti_start = 0
7
+
8
+ source_matches = Hash.new { |h, k| h[k] = [] }
9
+ source.each_with_index { |el, i| source_matches[el] << i }
10
+
11
+ subsequences = Hash.new { |k, v| k[v] = 0 }
12
+
13
+ target.each_with_index do |el, ti|
14
+ # Generate a new hash to use for the current iteration
15
+ _subsequences = Hash.new { |k, v| k[v] = 0 }
16
+
17
+ # This will return an array of indices that represent the positions
18
+ # of tokens
19
+ # in the source list that match the current token in the target list
20
+ source_matches[el].each do |si|
21
+ # This sets the current subsequence hash to have the length of any
22
+ # subsequence found at a the current source index (si) - 1. This is how
23
+ # subsequence lengths are tracked.
24
+ #
25
+ # If that length is greater than the current max the indexes where the
26
+ # sequence is found are persisted
27
+ if (_subsequences[si] = subsequences[si - 1] + 1) > max
28
+ max = _subsequences[si]
29
+ si_start = si - max + 1
30
+ ti_start = ti - max + 1
31
+ end
32
+ end
33
+
34
+ # Assign the current subsequence hash to the previous one so it can be passed
35
+ # into the next iteration.
36
+ subsequences = _subsequences
37
+ end
38
+
39
+ if max > 0
40
+ # If the max is greater than 0 a subsequence must have been found. This marks
41
+ # the sequence as being the same in both the source and the target. It then
42
+ # recursively looks at either side of the source and target list to try and
43
+ # find more subsequences.
44
+ start = [source[0...si_start], target[0...ti_start]]
45
+ middle = [
46
+ { change: '=', content: target[ti_start...(ti_start + max)] }
47
+ ]
48
+ finish = [
49
+ source[(si_start + max)..-1],
50
+ target[(ti_start + max)..-1]
51
+ ]
52
+
53
+ compare(*start) + middle + compare(*finish)
54
+ else
55
+ # If no subsequence is found then anything in the source list must be a
56
+ # removal and anything in the target must be an addition.
57
+ [].tap do |changes|
58
+ changes << { change: '-', content: source } if !source.empty?
59
+ changes << { change: '+', content: target } if !target.empty?
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,125 @@
1
+ require_relative "../lib/simplediff-ruby"
2
+ require "minitest/autorun"
3
+ require "minitest/reporters"
4
+
5
+ Minitest::Reporters.use!(Minitest::Reporters::DefaultReporter.new)
6
+ class SimpleDiffTest < MiniTest::Test
7
+ test_cases = {
8
+ insertions: [
9
+ {
10
+ source: [1, 3, 4],
11
+ target: [1, 2, 3, 4],
12
+ diff: [
13
+ {change: '=', content: [1]},
14
+ {change: '+', content: [2]},
15
+ {change: '=', content: [3, 4]}
16
+ ]
17
+ },
18
+ {
19
+ source: [1, 2, 3, 8, 9, 12, 13],
20
+ target: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15],
21
+ diff: [
22
+ {change: '=', content: [1, 2, 3]},
23
+ {change: '+', content: [4, 5, 6, 7]},
24
+ {change: '=', content: [8, 9]},
25
+ {change: '+', content: [10, 11]},
26
+ {change: '=', content: [12, 13]},
27
+ {change: '+', content: [14, 15]}
28
+ ]
29
+ },
30
+ {
31
+ source: [1, 2, 3, 4, 5],
32
+ target: [1, 2, 2, 3, 4, 5],
33
+ diff: [
34
+ {change: '=', content: [1]},
35
+ {change: '+', content: [2]},
36
+ {change: '=', content: [2, 3, 4, 5]}
37
+ ]
38
+ },
39
+ {
40
+ source: [1, 2, 3, 4, 5],
41
+ target: [1, 2, 2, 3, 4, 4, 5],
42
+ diff: [
43
+ {change: '=', content: [1]},
44
+ {change: '+', content: [2]},
45
+ {change: '=', content: [2, 3, 4]},
46
+ {change: '+', content: [4]},
47
+ {change: '=', content: [5]}
48
+ ]
49
+ },
50
+ {
51
+ source: [1, 2, 3, 4, 5],
52
+ target: [1, 2, 1, 2, 3, 3, 2, 1, 4, 5],
53
+ diff: [
54
+ {change: '+', content: [1, 2]},
55
+ {change: '=',content: [1, 2, 3]},
56
+ {change: '+', content: [3, 2, 1]},
57
+ {change: '=',content: [4, 5]}
58
+ ]
59
+ }
60
+ ],
61
+ deletions: [
62
+ {
63
+ source: [1, 2, 3, 4, 5],
64
+ target: [1, 2, 5],
65
+ diff: [
66
+ {change: '=', content: [1, 2]},
67
+ {change: '-', content: [3, 4]},
68
+ {change: '=', content: [5]}
69
+ ]
70
+ },
71
+ {
72
+ source: [1, 2, 3, 4, 5, 6, 7, 8],
73
+ target: [3, 6, 7],
74
+ diff: [
75
+ {change: '-', content: [1, 2]},
76
+ {change: '=', content: [3]},
77
+ {change: '-', content: [4, 5]},
78
+ {change: '=', content: [6, 7]},
79
+ {change: '-', content: [8]}
80
+ ]
81
+ },
82
+ {
83
+ source: [1, 2, 3, 4, 5, 1, 2, 3, 4, 5],
84
+ target: [1, 2, 3, 4, 5],
85
+ diff: [
86
+ {change: '=', content: [1, 2, 3, 4, 5]},
87
+ {change: '-', content: [1, 2, 3, 4, 5]}
88
+ ]
89
+ }
90
+ ],
91
+ changes: [
92
+ {
93
+ source: ['The', 'quick', 'brown', 'fox'],
94
+ target: ['The', 'slow', 'green', 'turtle'],
95
+ diff: [
96
+ {change: '=', content: ['The']},
97
+ {change: '-', content: ['quick', 'brown', 'fox']},
98
+ {change: '+', content: ['slow', 'green', 'turtle']}
99
+ ]
100
+ },
101
+ {
102
+ source: ['jumps', 'over', 'the', 'lazy', 'dog'],
103
+ target: ['walks', 'around', 'the', 'orange', 'cat'],
104
+ diff: [
105
+ {change: '-', content: ['jumps', 'over']},
106
+ {change: '+', content: ['walks', 'around']},
107
+ {change: '=', content: ['the']},
108
+ {change: '-', content: ['lazy', 'dog']},
109
+ {change: '+', content: ['orange', 'cat']}
110
+ ]
111
+ }
112
+ ]
113
+ }
114
+
115
+ test_cases.each do |key, cases|
116
+ cases.each do |test_case|
117
+ define_method("test_#{key}_#{test_case[:source]}-#{test_case[:target]}".to_sym) do
118
+ assert_equal(
119
+ test_case[:diff],
120
+ SimpleDiff.compare(test_case[:source], test_case[:target])
121
+ )
122
+ end
123
+ end
124
+ end
125
+ end
metadata ADDED
@@ -0,0 +1,78 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: simplediff-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - albertldlan
8
+ - JaredShay
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-11-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ">="
19
+ - !ruby/object:Gem::Version
20
+ version: '0'
21
+ type: :development
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ version: '0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: minitest-reporters
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ description: Ruby implemention of https://github.com/paulgb/simplediff.
43
+ email:
44
+ - albertldlan@gmail.com
45
+ - Jared.Shay@gmail.com
46
+ executables: []
47
+ extensions: []
48
+ extra_rdoc_files: []
49
+ files:
50
+ - README.md
51
+ - lib/simplediff-ruby.rb
52
+ - test/test.rb
53
+ homepage: https://github.com/albertldlan/simplediff-ruby
54
+ licenses:
55
+ - zlib-acknowledgement
56
+ metadata: {}
57
+ post_install_message:
58
+ rdoc_options: []
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: '0'
71
+ requirements: []
72
+ rubyforge_project:
73
+ rubygems_version: 2.5.1
74
+ signing_key:
75
+ specification_version: 4
76
+ summary: Ruby implemention of https://github.com/paulgb/simplediff.
77
+ test_files:
78
+ - test/test.rb