diff --git a/lib/utils/Omnom.ts b/lib/utils/Omnom.ts index 53c09a0..9d30f16 100644 --- a/lib/utils/Omnom.ts +++ b/lib/utils/Omnom.ts @@ -62,7 +62,7 @@ export class Omnom { if (original === undefined || original === null) return (original !== modified) && this.set(changePath, modified); - if (typeof original == 'number' && typeof modified == 'number' && original !== modified) { + if (typeof original === 'number' && typeof modified === 'number' && original !== modified) { if (this.options.atomicNumbers) return this.inc(changePath, modified - original); return this.set(changePath, modified); } @@ -91,67 +91,78 @@ export class Omnom { } private onArray(original: any[], modified: any[], changePath: string) { - var i, j; - // Check if we can get from original => modified using just pulls if (original.length > modified.length) { - var pulls = []; - for (i = 0, j = 0; i < original.length && j < modified.length; i++) { - if (this.almostEqual(original[i], modified[j])) j++; - else pulls.push(original[i]); - } - - for (; i < original.length; i++) - pulls.push(original[i]); - - if (j === modified.length) { - if (pulls.length === 1) return this.pull(changePath, pulls[0]); - // We can complete using just pulls - return pulls.forEach((pull) => this.pull(changePath, pull)); - } - - // If we have a smaller target array than our source, we will need to re-create it - // regardless (if we want to do so in a single operation anyway) - else return this.set(changePath, modified); + return this.onSmallerArray(original, modified, changePath); } // Check if we can get from original => modified using just pushes if (original.length < modified.length) { - var canPush = true; - for (i = 0; i < original.length; i++) - if (this.almostEqual(original[i], modified[i]) < 1) { - canPush = false; - break; - } - - if (canPush) { - for (i = original.length; i < modified.length; i++) - this.push(changePath, modified[i]); - return; - } + return this.onLargerArray(original, modified, changePath); } // Otherwise, we need to use $set to generate the new array + return this.onSimilarArray(original, modified, changePath); + } - // Check how many manipulations would need to be performed, if it's more than half the array size - // then rather re-create the array - - var sets = []; - var partials = []; - for (i = 0; i < modified.length; i++) { - var equality = this.almostEqual(original[i], modified[i]); - if (equality === 0) sets.push(i); - else if (equality < 1) partials.push(i); - } - - if (sets.length > modified.length / 2) - return this.set(changePath, modified); - - for (i = 0; i < sets.length; i++) - this.set(this.resolve(changePath, sets[i].toString()), modified[sets[i]]); - - for (i = 0; i < partials.length; i++) - this.onObject(original[partials[i]], modified[partials[i]], this.resolve(changePath, partials[i].toString())); + private onSmallerArray(original: any[], modified: any[], changePath: string) { + let pulls = []; + let i = 0; + let j = 0; + + for (; i < original.length && j < modified.length; i++) { + if (this.almostEqual(original[i], modified[j])) j++; + else pulls.push(original[i]); + } + + for (; i < original.length; i++) + pulls.push(original[i]); + + if (j === modified.length) { + if (pulls.length === 1) return this.pull(changePath, pulls[0]); + // We can complete using just pulls + return pulls.forEach((pull) => this.pull(changePath, pull)); + } + + // If we have a smaller target array than our source, we will need to re-create it + // regardless (if we want to do so in a single operation anyway) + else return this.set(changePath, modified); + } + + private onLargerArray(original: any[], modified: any[], changePath: string) { + let canPush = true; + for (let i = 0; i < original.length; i++) + if (this.almostEqual(original[i], modified[i]) < 1) { + canPush = false; + break; + } + + if (canPush) { + for (let i = original.length; i < modified.length; i++) + this.push(changePath, modified[i]); + return; + } + } + + private onSimilarArray(original: any[], modified: any[], changePath: string) { + // Check how many manipulations would need to be performed, if it's more than half the array size + // then rather re-create the array + let sets = []; + let partials = []; + for (let i = 0; i < modified.length; i++) { + let equality = this.almostEqual(original[i], modified[i]); + if (equality === 0) sets.push(i); + else if (equality < 1) partials.push(i); + } + + if (sets.length > modified.length / 2) + return this.set(changePath, modified); + + for (let i = 0; i < sets.length; i++) + this.set(this.resolve(changePath, sets[i].toString()), modified[sets[i]]); + + for (let i = 0; i < partials.length; i++) + this.onObject(original[partials[i]], modified[partials[i]], this.resolve(changePath, partials[i].toString())); } private set(path: string, value: any) { @@ -214,7 +225,7 @@ export class Omnom { } private resolve(...args) { - var validArguments = []; + let validArguments = []; args.forEach(function (arg) { if (arg) validArguments.push(arg); }); @@ -225,18 +236,18 @@ export class Omnom { private almostEqual(o1: any, o2: any) { if (!_.isPlainObject(o1) || !_.isPlainObject(o2)) return o1 == o2 ? 1 : 0; - var o1i, o1k = Object.keys(o1); - var o2k = Object.keys(o2); + let object1KeyIndex, object1Keys = Object.keys(o1); + let object2Keys = Object.keys(o2); - var commonKeys = []; - for (o1i = 0; o1i < o1k.length; o1i++) - if (~o2k.indexOf(o1k[o1i])) commonKeys.push(o1k[o1i]); + let commonKeys = []; + for (object1KeyIndex = 0; object1KeyIndex < object1Keys.length; object1KeyIndex++) + if (~object2Keys.indexOf(object1Keys[object1KeyIndex])) commonKeys.push(object1Keys[object1KeyIndex]); - var totalKeys = o1k.length + o2k.length - commonKeys.length; - var keysDifference = totalKeys - commonKeys.length; + let totalKeys = object1Keys.length + object2Keys.length - commonKeys.length; + let keysDifference = totalKeys - commonKeys.length; - var requiredChanges = 0; - for (var i = 0; i < commonKeys.length; i++) + let requiredChanges = 0; + for (let i = 0; i < commonKeys.length; i++) if (this.almostEqual(o1[commonKeys[i]], o2[commonKeys[i]]) < 1) requiredChanges++; return 1 - (keysDifference / totalKeys) - (requiredChanges / commonKeys.length);