simplediff-ruby 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|