Skip to content
HashDiff is a ruby library to to compute the smallest difference between two hashes
Find file
Pull request Compare This branch is 38 commits behind liufengyun:master.
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Failed to load latest commit information.
lib
spec
.gitignore
.rspec
.travis.yml
.yardopts
Gemfile
Gemfile.lock
LICENSE
README.md
Rakefile
changelog.md
hashdiff.gemspec

README.md

HashDiff

Build Status

HashDiff is a ruby library to compute the smallest difference between two hashes.

Demo: HashDiff

Docs: Documentation

Why HashDiff?

Given two Hashes A and B, sometimes you face the question: what's the smallest changes that can be made to change A to B?

An algorithm responds to this question has to do following:

  • Generate a list of additions, deletions and changes, so that A + ChangeSet = B and B - ChangeSet = A.
  • Compute recursively -- Arrays and Hashes may be nested arbitrarily in A or B.
  • Compute the smallest change -- it should recoganize similar child Hashes or child Arrays between A and B.

HashDiff answers the question above in an opinionated approach:

  • Hash can be represented as a list of (dot-syntax-path, value) pairs. For example, {a:[{c:2}]} can be represented as ["a[0].c", 2].
  • The change set can be represented using the do-syntax representation. For example, [['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]].
  • It compares Arrays using LCS(longest common subsequence) algorithm.
  • It recoganize similar Hashes in Array using a similarity value(0 < similarity <= 1).

Compatibility

HashDiff is tested against 1.9.2, 1.9.3 and ruby-head. It should work on other versions as well.

Usage

If you're using bundler, add following to the Gemfile:

gem 'hashdiff'

Or, you can run gem install hashdiff, then add following line to your ruby file which uses HashDiff:

require 'hashdiff'

Quick Start

Diff

Two simple hash:

a = {a:3, b:2}
b = {}

diff = HashDiff.diff(a, b)
diff.should == [['-', 'a', 3], ['-', 'b', 2]]

More complex hash:

a = {a:{x:2, y:3, z:4}, b:{x:3, z:45}}
b = {a:{y:3}, b:{y:3, z:30}}

diff = HashDiff.diff(a, b)
diff.should == [['-', 'a.x', 2], ['-', 'a.z', 4], ['-', 'b.x', 3], ['~', 'b.z', 45, 30], ['+', 'b.y', 3]]

Array in hash:

a = {a:[{x:2, y:3, z:4}, {x:11, y:22, z:33}], b:{x:3, z:45}}
b = {a:[{y:3}, {x:11, z:33}], b:{y:22}}

diff = HashDiff.best_diff(a, b)
diff.should == [['-', 'a[0].x', 2], ['-', 'a[0].z', 4], ['-', 'a[1].y', 22], ['-', 'b.x', 3], ['-', 'b.z', 45], ['+', 'b.y', 22]]

Patch

patch example:

a = {a: 3}
b = {a: {a1: 1, a2: 2}}

diff = HashDiff.diff(a, b)
HashDiff.patch!(a, diff).should == b

unpatch example:

a = [{a: 1, b: 2, c: 3, d: 4, e: 5}, {x: 5, y: 6, z: 3}, 1]
b = [1, {a: 1, b: 2, c: 3, e: 5}]

diff = HashDiff.diff(a, b) # diff two array is OK
HashDiff.unpatch!(b, diff).should == a

License

HashDiff is distributed under the MIT-LICENSE.

Something went wrong with that request. Please try again.