odiff
A value difference generator that can generate a list of differences between one javascript value and another. It recursively finds differences within arrays and objects.
var a = [{a:1,b:2,c:3}, {x:1,y: 2, z:3}, {w:9,q:8,r:7}]
var b = [{a:1,b:2,c:3},{t:4,y:5,u:6},{x:1,y:'3',z:3},{t:9,y:9,u:9},{w:9,q:8,r:7}]
var diffs = odiff(a,b)
/* diffs now contains:
[{type: 'add', path:[], index: 2, vals: [{t:9,y:9,u:9}]},
{type: 'set', path:[1,'y'], val: '3'},
{type: 'add', path:[], index: 1, vals: [{t:4,y:5,u:6}]}
]
*/
This differencing algorithm is intended to make object differences easy to manage when you need to update an object in a way other than simply copying the reference. An example is if you need to create a database query to update a record based on the changes between two objects. It also works in a basic way on primitives (no string differencing tho).
While this algorithm puts in some effort to make the number of change records minimal, it by no means generates an absolutely minimal set of changes. It also doesn't handle compressing string differences in any way. For these reasons, this algorithm is not ideal for use in sending changes over the wire, especially if your data contains lots of small changes to large strings.
Other algorithms I found either had undesirable behavior when dealing with array inserts ( flitbit/diff, cosmicanant/recursive-diff, ackrause/ObjectCompare, thomseddon/docdiff ), had weird nested difference formats that make things harder ( NV/objectDiff.js ), didn't describe their behavior at all ( aogriffiths/jsondiff-js, benjamine/JsonDiffPatch ), or all three. Also some only work on objects (not arrays) ( Evaw/objectDiff, omgaz/js-diff ).
npm install odiff
Accessing odiff:
// typescript
import odiff from "odiff";
// node.js
var odiff = require('odiff')
// amd
require.config({paths: {odiff: '../generatedBuilds/odiff.umd.js'}})
require(['odiff'], function(odiff) { /* your code */ })
// global variable
<script src="https://github.com/Tixit/odiff/raw/master/odiff.umd.js"></script>
odiff; // odiff.umd.js can define odiff globally if you really
// want to shun module-based design
Using odiff:
odiff(valueA, valueB)
- Returns an array of changes that, when applied to valueA, will turn that value into valueB. The results are also build such that you can pick and choose what changes to do, and as long as you do them (selectively) in order, the changes will work properly.
Each element in the resulting array has the following members:
type
- Either "set"
, "unset"
, "add"
, or "rm"
path
- An array representing the path from the root object. For example, ["a",2,"b"]
represents valueA.a[2].b
. Will be an empty array if the change applies to the top-level object (ie valueA
directly).val
- The value the indicated property was changed to. Only defined for the "set"
type.index
- The index at which an item was added or removed from an array. Only defined for the "add"
and "rm"
types.vals
- An array of values added into the indiconly availableated property. Only defined for the "add"
and "rm"
types.Odiff also exposes two functions used internally:
odiff.equal(a,b)
- Returns true if the two values are equal, false otherwise. NaN
is treated as equal to itself.
odiff.similar(a,b)
- Returns true if the two values are similar, false otherwise. "Similar" is defined as having less than two shallow inner values different (as long as not 100% of the values are different) or having fewer than 10% of its shallow values different.
NaN
is treated as equal to itself.
The differencing algorithm is intended to run well on values that are pretty similar. Some properties of the algorithm:
valueA
in order, you will get valueB
. It does this by reversing the order in which array changes are listed.value
key of the change item.Anything helps:
How to submit pull requests:
npm install
at its rootsimilar
function that would cause unoptimized diffs. rm
where the index was previously the last index removed and changed to the index being the first item removed.Released under the MIT license: http://opensource.org/licenses/MIT