Method: HashDiff.best_diff

Defined in:
lib/hashdiff/diff.rb

.best_diff(obj1, obj2, options = {}) {|path, value1, value2| ... } ⇒ Array

Best diff two objects, which tries to generate the smallest change set using different similarity values.

HashDiff.best_diff is useful in case of comparing two objects which include similar hashes in arrays.

Examples:

a = {'x' => [{'a' => 1, 'c' => 3, 'e' => 5}, {'y' => 3}]}
b = {'x' => [{'a' => 1, 'b' => 2, 'e' => 5}] }
diff = HashDiff.best_diff(a, b)
diff.should == [['-', 'x[0].c', 3], ['+', 'x[0].b', 2], ['-', 'x[1].y', 3], ['-', 'x[1]', {}]]

Parameters:

  • obj1 (Array, Hash)
  • obj2 (Array, Hash)
  • options (Hash) (defaults to: {})

    the options to use when comparing

    • :strict (Boolean) [true] whether numeric values will be compared on type as well as value. Set to false to allow comparing Fixnum, Float, BigDecimal to each other

    • :delimiter (String) [‘.’] the delimiter used when returning nested key references

    • :numeric_tolerance (Numeric) [0] should be a positive numeric value. Value by which numeric differences must be greater than. By default, numeric values are compared exactly; with the :tolerance option, the difference between numeric values must be greater than the given value.

    • :strip (Boolean) [false] whether or not to call #strip on strings before comparing

Yields:

  • (path, value1, value2)

    Optional block is used to compare each value, instead of default #==. If the block returns value other than true of false, then other specified comparison options will be used to do the comparison.

Returns:

  • (Array)

    an array of changes. e.g. [[ ‘+’, ‘a.b’, ‘45’ ], [ ‘-’, ‘a.c’, ‘5’ ], [ ‘~’, ‘a.x’, ‘45’, ‘63’]]

Since:

  • 0.0.1



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/hashdiff/diff.rb', line 27

def self.best_diff(obj1, obj2, options = {}, &block)
  options[:comparison] = block if block_given?

  opts = { :similarity => 0.3 }.merge!(options)
  diffs_1 = diff(obj1, obj2, opts)
  count_1 = count_diff diffs_1

  opts = { :similarity => 0.5 }.merge!(options)
  diffs_2 = diff(obj1, obj2, opts)
  count_2 = count_diff diffs_2

  opts = { :similarity => 0.8 }.merge!(options)
  diffs_3 = diff(obj1, obj2, opts)
  count_3 = count_diff diffs_3

  count, diffs = count_1 < count_2 ? [count_1, diffs_1] : [count_2, diffs_2]
  diffs = count < count_3 ? diffs : diffs_3
end