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.
- checksums.yaml +7 -0
- data/README.md +39 -0
- data/lib/simplediff-ruby.rb +63 -0
- data/test/test.rb +125 -0
- metadata +78 -0
checksums.yaml
ADDED
@@ -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
|
data/README.md
ADDED
@@ -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
|
data/test/test.rb
ADDED
@@ -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
|