hashdiff 0.0.5 → 0.0.6
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.
- data/Gemfile.lock +1 -1
- data/README.md +4 -1
- data/changelog.md +4 -0
- data/lib/hashdiff/diff.rb +9 -8
- data/lib/hashdiff/patch.rb +6 -4
- data/lib/hashdiff/util.rb +4 -2
- data/lib/hashdiff/version.rb +1 -1
- data/spec/hashdiff/best_diff_spec.rb +9 -0
- data/spec/hashdiff/diff_spec.rb +8 -0
- data/spec/hashdiff/util_spec.rb +6 -0
- metadata +24 -9
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -25,7 +25,6 @@ HashDiff answers the question above in an opinionated approach:
|
|
25
25
|
* It compares Arrays using LCS(longest common subsequence) algorithm.
|
26
26
|
* It recoganize similar Hashes in Array using a similarity value(0 < similarity <= 1).
|
27
27
|
|
28
|
-
|
29
28
|
## Compatibility
|
30
29
|
|
31
30
|
HashDiff is tested against `1.9.2`, `1.9.3` and `ruby-head`. It should work on other versions as well.
|
@@ -86,6 +85,10 @@ unpatch example:
|
|
86
85
|
diff = HashDiff.diff(a, b) # diff two array is OK
|
87
86
|
HashDiff.unpatch!(b, diff).should == a
|
88
87
|
|
88
|
+
## Contributors
|
89
|
+
|
90
|
+
- @liufengyun
|
91
|
+
- @m-o-e
|
89
92
|
|
90
93
|
## License
|
91
94
|
|
data/changelog.md
CHANGED
data/lib/hashdiff/diff.rb
CHANGED
@@ -17,14 +17,14 @@ module HashDiff
|
|
17
17
|
# diff.should == [['-', 'x[0].c', 3], ['+', 'x[0].b', 2], ['-', 'x[1].y', 3], ['-', 'x[1]', {}]]
|
18
18
|
#
|
19
19
|
# @since 0.0.1
|
20
|
-
def self.best_diff(obj1, obj2)
|
21
|
-
diffs_1 = diff(obj1, obj2, "", 0.3)
|
20
|
+
def self.best_diff(obj1, obj2, delimiter='.')
|
21
|
+
diffs_1 = diff(obj1, obj2, "", 0.3, delimiter)
|
22
22
|
count_1 = count_diff diffs_1
|
23
23
|
|
24
|
-
diffs_2 = diff(obj1, obj2, "", 0.5)
|
24
|
+
diffs_2 = diff(obj1, obj2, "", 0.5, delimiter)
|
25
25
|
count_2 = count_diff diffs_2
|
26
26
|
|
27
|
-
diffs_3 = diff(obj1, obj2, "", 0.8)
|
27
|
+
diffs_3 = diff(obj1, obj2, "", 0.8, delimiter)
|
28
28
|
count_3 = count_diff diffs_3
|
29
29
|
|
30
30
|
count, diffs = count_1 < count_2 ? [count_1, diffs_1] : [count_2, diffs_2]
|
@@ -38,6 +38,7 @@ module HashDiff
|
|
38
38
|
# @param [float] similarity A value > 0 and <= 1.
|
39
39
|
# This parameter should be ignored in common usage.
|
40
40
|
# Similarity is only meaningful if there're similar objects in arrays. See {best_diff}.
|
41
|
+
# @param [String] delimiter Delimiter for returned property-string
|
41
42
|
#
|
42
43
|
# @return [Array] an array of changes.
|
43
44
|
# e.g. [[ '+', 'a.b', '45' ], [ '-', 'a.c', '5' ], [ '~', 'a.x', '45', '63']]
|
@@ -50,7 +51,7 @@ module HashDiff
|
|
50
51
|
# diff.should == [['-', 'b.b1', 1], ['-', 'b.b2', 2]]
|
51
52
|
#
|
52
53
|
# @since 0.0.1
|
53
|
-
def self.diff(obj1, obj2, prefix = "", similarity = 0.8)
|
54
|
+
def self.diff(obj1, obj2, prefix = "", similarity = 0.8, delimiter='.')
|
54
55
|
if obj1.nil? and obj2.nil?
|
55
56
|
return []
|
56
57
|
end
|
@@ -72,7 +73,7 @@ module HashDiff
|
|
72
73
|
changeset = diff_array(obj1, obj2, similarity) do |lcs|
|
73
74
|
# use a's index for similarity
|
74
75
|
lcs.each do |pair|
|
75
|
-
result.concat(diff(obj1[pair[0]], obj2[pair[1]], "#{prefix}[#{pair[0]}]", similarity))
|
76
|
+
result.concat(diff(obj1[pair[0]], obj2[pair[1]], "#{prefix}[#{pair[0]}]", similarity, delimiter))
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
@@ -84,7 +85,7 @@ module HashDiff
|
|
84
85
|
end
|
85
86
|
end
|
86
87
|
elsif obj1.is_a?(Hash)
|
87
|
-
prefix = prefix.empty? ? "" : "#{prefix}
|
88
|
+
prefix = prefix.empty? ? "" : "#{prefix}#{delimiter}"
|
88
89
|
|
89
90
|
deleted_keys = []
|
90
91
|
common_keys = []
|
@@ -101,7 +102,7 @@ module HashDiff
|
|
101
102
|
deleted_keys.each {|k| result << ['-', "#{prefix}#{k}", obj1[k]] }
|
102
103
|
|
103
104
|
# recursive comparison for common keys
|
104
|
-
common_keys.each {|k| result.concat(diff(obj1[k], obj2[k], "#{prefix}#{k}", similarity)) }
|
105
|
+
common_keys.each {|k| result.concat(diff(obj1[k], obj2[k], "#{prefix}#{k}", similarity, delimiter)) }
|
105
106
|
|
106
107
|
# added properties
|
107
108
|
obj2.each do |k, v|
|
data/lib/hashdiff/patch.rb
CHANGED
@@ -7,13 +7,14 @@ module HashDiff
|
|
7
7
|
#
|
8
8
|
# @param [Hash, Array] obj the object to be patchted, can be an Array of a Hash
|
9
9
|
# @param [Array] changes e.g. [[ '+', 'a.b', '45' ], [ '-', 'a.c', '5' ], [ '~', 'a.x', '45', '63']]
|
10
|
+
# @param [String] delimiter Property-string delimiter
|
10
11
|
#
|
11
12
|
# @return the object after patch
|
12
13
|
#
|
13
14
|
# @since 0.0.1
|
14
|
-
def self.patch!(obj, changes)
|
15
|
+
def self.patch!(obj, changes, delimiter='.')
|
15
16
|
changes.each do |change|
|
16
|
-
parts = decode_property_path(change[1])
|
17
|
+
parts = decode_property_path(change[1], delimiter)
|
17
18
|
last_part = parts.last
|
18
19
|
|
19
20
|
parent_node = node(obj, parts[0, parts.size-1])
|
@@ -42,13 +43,14 @@ module HashDiff
|
|
42
43
|
#
|
43
44
|
# @param [Hash, Array] obj the object to be unpatchted, can be an Array of a Hash
|
44
45
|
# @param [Array] changes e.g. [[ '+', 'a.b', '45' ], [ '-', 'a.c', '5' ], [ '~', 'a.x', '45', '63']]
|
46
|
+
# @param [String] delimiter Property-string delimiter
|
45
47
|
#
|
46
48
|
# @return the object after unpatch
|
47
49
|
#
|
48
50
|
# @since 0.0.1
|
49
|
-
def self.unpatch!(obj, changes)
|
51
|
+
def self.unpatch!(obj, changes, delimiter='.')
|
50
52
|
changes.reverse_each do |change|
|
51
|
-
parts = decode_property_path(change[1])
|
53
|
+
parts = decode_property_path(change[1], delimiter)
|
52
54
|
last_part = parts.last
|
53
55
|
|
54
56
|
parent_node = node(obj, parts[0, parts.size-1])
|
data/lib/hashdiff/util.rb
CHANGED
@@ -47,10 +47,12 @@ module HashDiff
|
|
47
47
|
# @private
|
48
48
|
#
|
49
49
|
# decode property path into an array
|
50
|
+
# @param [String] path Property-string
|
51
|
+
# @param [String] delimiter Property-string delimiter
|
50
52
|
#
|
51
53
|
# e.g. "a.b[3].c" => ['a', 'b', 3, 'c']
|
52
|
-
def self.decode_property_path(path)
|
53
|
-
parts = path.split(
|
54
|
+
def self.decode_property_path(path, delimiter='.')
|
55
|
+
parts = path.split(delimiter).collect do |part|
|
54
56
|
if part =~ /^(\w*)\[(\d+)\]$/
|
55
57
|
if $1.size > 0
|
56
58
|
[$1, $2.to_i]
|
data/lib/hashdiff/version.rb
CHANGED
@@ -9,6 +9,15 @@ describe HashDiff do
|
|
9
9
|
diff.should == [["-", "x[0].c", 3], ["+", "x[0].b", 2], ["-", "x[1]", {"y"=>3}]]
|
10
10
|
end
|
11
11
|
|
12
|
+
it "should use custom delimiter when provided" do
|
13
|
+
a = {'x' => [{'a' => 1, 'c' => 3, 'e' => 5}, {'y' => 3}]}
|
14
|
+
b = {'x' => [{'a' => 1, 'b' => 2, 'e' => 5}] }
|
15
|
+
|
16
|
+
diff = HashDiff.best_diff(a, b, "\t")
|
17
|
+
diff.should == [["-", "x[0]\tc", 3], ["+", "x[0]\tb", 2], ["-", "x[1]", {"y"=>3}]]
|
18
|
+
end
|
19
|
+
|
20
|
+
|
12
21
|
it "should be able to best diff array in hash" do
|
13
22
|
a = {"menu" => {
|
14
23
|
"id" => "file",
|
data/spec/hashdiff/diff_spec.rb
CHANGED
@@ -123,5 +123,13 @@ describe HashDiff do
|
|
123
123
|
diff.should == [["-", "[0].d", 4], ["-", "[1]", {"x"=>5, "y"=>6, "z"=>3}]]
|
124
124
|
end
|
125
125
|
|
126
|
+
it "should use custom delimiter when provided" do
|
127
|
+
a = [{'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}, {'x' => 5, 'y' => 6, 'z' => 3}, 3]
|
128
|
+
b = [{'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}, 3]
|
129
|
+
|
130
|
+
diff = HashDiff.diff(a, b, "", 0.8, "\t")
|
131
|
+
diff.should == [["-", "[0]\td", 4], ["-", "[1]", {"x"=>5, "y"=>6, "z"=>3}]]
|
132
|
+
end
|
133
|
+
|
126
134
|
end
|
127
135
|
|
data/spec/hashdiff/util_spec.rb
CHANGED
@@ -6,6 +6,12 @@ describe HashDiff do
|
|
6
6
|
decoded.should == ['a', 'b', 0, 'c', 'city', 5]
|
7
7
|
end
|
8
8
|
|
9
|
+
it "should be able to decode property path with custom delimiter" do
|
10
|
+
decoded = HashDiff.send(:decode_property_path, "a\tb[0]\tc\tcity[5]", "\t")
|
11
|
+
decoded.should == ['a', 'b', 0, 'c', 'city', 5]
|
12
|
+
end
|
13
|
+
|
14
|
+
|
9
15
|
it "should be able to tell similiar hash" do
|
10
16
|
a = {'a' => 1, 'b' => 2, 'c' => 3, 'd' => 4, 'e' => 5}
|
11
17
|
b = {'a' => 1, 'b' => 2, 'c' => 3, 'e' => 5}
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashdiff
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
16
|
-
requirement:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,15 @@ dependencies:
|
|
21
21
|
version: '2.0'
|
22
22
|
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements:
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '2.0'
|
25
30
|
- !ruby/object:Gem::Dependency
|
26
31
|
name: yard
|
27
|
-
requirement:
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
28
33
|
none: false
|
29
34
|
requirements:
|
30
35
|
- - ! '>='
|
@@ -32,10 +37,15 @@ dependencies:
|
|
32
37
|
version: '0'
|
33
38
|
type: :development
|
34
39
|
prerelease: false
|
35
|
-
version_requirements:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
36
46
|
- !ruby/object:Gem::Dependency
|
37
47
|
name: bluecloth
|
38
|
-
requirement:
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
39
49
|
none: false
|
40
50
|
requirements:
|
41
51
|
- - ! '>='
|
@@ -43,7 +53,12 @@ dependencies:
|
|
43
53
|
version: '0'
|
44
54
|
type: :development
|
45
55
|
prerelease: false
|
46
|
-
version_requirements:
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
none: false
|
58
|
+
requirements:
|
59
|
+
- - ! '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
47
62
|
description: ! ' HashDiff is a diff lib to compute the smallest difference between
|
48
63
|
two hashes. '
|
49
64
|
email:
|
@@ -96,7 +111,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
96
111
|
version: '0'
|
97
112
|
requirements: []
|
98
113
|
rubyforge_project:
|
99
|
-
rubygems_version: 1.8.
|
114
|
+
rubygems_version: 1.8.24
|
100
115
|
signing_key:
|
101
116
|
specification_version: 3
|
102
117
|
summary: HashDiff is a diff lib to compute the smallest difference between two hashes.
|