Wie mache ich einen tiefen Vergleich zwischen 2 Objekten mit lodash?

309

Ich habe 2 verschachtelte Objekte, die unterschiedlich sind, und ich muss wissen, ob sie sich in einer ihrer verschachtelten Eigenschaften unterscheiden.

var a = {};
var b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

Das Objekt könnte mit verschachtelten Eigenschaften viel komplexer sein. Aber dieser ist ein gutes Beispiel. Ich habe die Möglichkeit, rekursive Funktionen oder etwas mit lodash zu verwenden ...

JLavoie
quelle
Zum tiefen Vergleich stackoverflow.com/a/46003894/696535
Pawel
7
_.isEqual(value, other)Führt einen umfassenden Vergleich zwischen zwei Werten durch, um festzustellen, ob sie gleichwertig sind. lodash.com/docs#isEqual
Lukas Liesis
JSON.stringify ()
xgqfrms
10
JSON.stringify () ist falsch: JSON.stringify ({a: 1, b: 2})! == JSON.stringify ({b: 2, a: 1})
Shl

Antworten:

475

Eine einfache und elegante Lösung ist die Verwendung _.isEqual, die einen tiefen Vergleich durchführt:

var a = {};
var b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

_.isEqual(a, b); // returns false if different

Diese Lösung zeigt jedoch nicht, welche Eigenschaft unterschiedlich ist.

http://jsfiddle.net/bdkeyn0h/

JLavoie
quelle
2
Ich weiß, dass die Antwort ziemlich alt ist, aber ich möchte hinzufügen, dass _.isEqualdas ziemlich schwierig sein kann. Wenn Sie das Objekt kopieren und dort einige Werte ändern, wird weiterhin true angezeigt, da die Referenz dieselbe ist. Daher sollte man bei der Verwendung dieser Funktion vorsichtig sein.
Oruckdeschel
23
@oruckdeschel Wenn die Referenz dieselbe ist, ist es dasselbe Objekt. daher ist es gleich. Dies ist ein Zeiger, der schwierig ist, nicht lodash. lodash ist super.
Kerl Mograbi
265

Wenn Sie wissen möchten, welche Eigenschaften unterschiedlich sind, verwenden Sie redu () :

_.reduce(a, function(result, value, key) {
    return _.isEqual(value, b[key]) ?
        result : result.concat(key);
}, []);
// → [ "prop2" ]
Adam Boduch
quelle
36
Beachten Sie, dass dadurch nur die unterschiedlichen Eigenschaften der ersten Ebene ausgegeben werden. (Es ist also nicht wirklich tief im Sinne der Ausgabe der Eigenschaften, die unterschiedlich sind.)
Kerl
16
Dies nimmt auch keine Eigenschaften in b auf, die nicht in a sind.
Ed Staub
3
und _.reduce(a, (result, value, key) => _.isEqual(value, b[key]) ? result : result.concat(key), [])für eine einzeilige ES6-Lösung
Dotgreg
1
Eine Version, die den Schlüssel enthält: Wertlet edited = _.reduce(a, function(result, value, key) { return _.isEqual(value, b[key]) ? result : result.concat( { [key]: value } ); }, []);
Aline Matos
47

Für alle, die über diesen Thread stolpern, ist hier eine vollständigere Lösung. Es werden zwei Objekte verglichen und Sie erhalten den Schlüssel aller Eigenschaften, die entweder nur in Objekt1 , nur in Objekt2 oder beide in Objekt1 und Objekt2 enthalten sind, aber unterschiedliche Werte haben :

/*
 * Compare two objects by reducing an array of keys in obj1, having the
 * keys in obj2 as the intial value of the result. Key points:
 *
 * - All keys of obj2 are initially in the result.
 *
 * - If the loop finds a key (from obj1, remember) not in obj2, it adds
 *   it to the result.
 *
 * - If the loop finds a key that are both in obj1 and obj2, it compares
 *   the value. If it's the same value, the key is removed from the result.
 */
function getObjectDiff(obj1, obj2) {
    const diff = Object.keys(obj1).reduce((result, key) => {
        if (!obj2.hasOwnProperty(key)) {
            result.push(key);
        } else if (_.isEqual(obj1[key], obj2[key])) {
            const resultKeyIndex = result.indexOf(key);
            result.splice(resultKeyIndex, 1);
        }
        return result;
    }, Object.keys(obj2));

    return diff;
}

Hier ist eine Beispielausgabe:

// Test
let obj1 = {
    a: 1,
    b: 2,
    c: { foo: 1, bar: 2},
    d: { baz: 1, bat: 2 }
}

let obj2 = {
    b: 2, 
    c: { foo: 1, bar: 'monkey'}, 
    d: { baz: 1, bat: 2 }
    e: 1
}
getObjectDiff(obj1, obj2)
// ["c", "e", "a"]

Wenn Sie sich nicht für verschachtelte Objekte interessieren und lodash überspringen möchten, können Sie das _.isEqualdurch einen Normalwertvergleich ersetzen , z obj1[key] === obj2[key].

Johan Persson
quelle
Diese gewählte Antwort ist richtig, um nur die Gleichheit zu testen. Wenn Sie wissen müssen, was die Unterschiede sind, gibt es keine offensichtliche Möglichkeit, sie aufzulisten, aber diese Antwort ist ziemlich gut. Geben Sie einfach eine Liste der Eigenschaftsschlüssel der obersten Ebene an, bei denen es einen Unterschied gibt. (Und es gibt die Antwort als eine Funktion, die es verwendbar macht.)
Sigfried
Was ist der Unterschied zwischen der Verwendung von _.isEqual (obj1, obj2)? Was bewirkt das Hinzufügen der Prüfung für hasOwnProperty, was _.isEqual nicht tut? Ich war unter der Annahme, dass wenn obj1 eine Eigenschaft hätte, die obj2 nicht hätte, _.isEqual nicht true zurückgeben würde ..?
Jaked222
2
@ Jaked222 - Der Unterschied besteht darin, dass isEqual einen Booleschen Wert zurückgibt, der angibt, ob die Objekte gleich sind oder nicht, während die obige Funktion Ihnen sagt, was zwischen den beiden Objekten unterschiedlich ist (wenn sie unterschiedlich sind). Wenn Sie nur wissen möchten, ob zwei Objekte gleich sind, reicht isEqual völlig aus. In vielen Fällen möchten Sie jedoch wissen, was der Unterschied zwischen zwei Objekten ist. Ein Beispiel könnte sein, wenn Sie Änderungen vor und nach etwas erkennen und dann ein Ereignis basierend auf den Änderungen auslösen möchten.
Johan Persson
30

Basierend auf der Antwort von Adam Boduch habe ich diese Funktion geschrieben, die zwei Objekte im tiefsten Sinne vergleicht und Pfade mit unterschiedlichen Werten sowie Pfade zurückgibt , die auf dem einen oder anderen Objekt fehlen.

Der Code wurde nicht mit Blick auf Effizienz geschrieben, und Verbesserungen in dieser Hinsicht sind sehr willkommen, aber hier ist die Grundform:

var compare = function (a, b) {

  var result = {
    different: [],
    missing_from_first: [],
    missing_from_second: []
  };

  _.reduce(a, function (result, value, key) {
    if (b.hasOwnProperty(key)) {
      if (_.isEqual(value, b[key])) {
        return result;
      } else {
        if (typeof (a[key]) != typeof ({}) || typeof (b[key]) != typeof ({})) {
          //dead end.
          result.different.push(key);
          return result;
        } else {
          var deeper = compare(a[key], b[key]);
          result.different = result.different.concat(_.map(deeper.different, (sub_path) => {
            return key + "." + sub_path;
          }));

          result.missing_from_second = result.missing_from_second.concat(_.map(deeper.missing_from_second, (sub_path) => {
            return key + "." + sub_path;
          }));

          result.missing_from_first = result.missing_from_first.concat(_.map(deeper.missing_from_first, (sub_path) => {
            return key + "." + sub_path;
          }));
          return result;
        }
      }
    } else {
      result.missing_from_second.push(key);
      return result;
    }
  }, result);

  _.reduce(b, function (result, value, key) {
    if (a.hasOwnProperty(key)) {
      return result;
    } else {
      result.missing_from_first.push(key);
      return result;
    }
  }, result);

  return result;
}

Sie können den Code mit diesem Snippet ausprobieren (es wird empfohlen, ihn im Ganzseitenmodus auszuführen):

Rashad Saleh
quelle
4
Ich habe gerade den Fehler behoben, aber um Sie wissen zu lassen, sollten Sie die Schlüsselexistenz innerhalb eines Objekts b mit b.hasOwnProperty(key)oderkey in b nicht mit überprüfen b[key] != undefined. Mit der alten Version, die verwendet wurde b[key] != undefined, hat die Funktion ein falsches Diff für Objekte zurückgegeben undefined, die wie in enthalten compare({disabled: undefined}, {disabled: undefined}). In der Tat hatte die alte Version auch Probleme mit null; Sie können solche Probleme vermeiden, indem Sie immer ===und!== anstelle von ==und verwenden !=.
Rory O'Kane
23

Hier ist eine kurze Lösung:

_.differenceWith(a, b, _.isEqual);
DPG
quelle
7
Scheint für mich nicht mit Objekten zu funktionieren. Gibt stattdessen ein leeres Array zurück.
Tomhughes
2
Auch leeres Array mit Lodash 4.17.4
aristidesfl
@ Z.Khullah Wenn es so funktioniert hat, ist es nicht dokumentiert.
Brendon
1
@Brendon, @THughes, @aristidesfl Entschuldigung, ich habe Dinge gemischt, es funktioniert mit Arrays von Objekten, aber nicht für tiefe Objektvergleiche. Wie sich herausstellt, wird lodash nur zurückgegeben, wenn keiner der Parameter Arrays sind [].
Z. Khullah
7

Um rekursiv zu zeigen, wie sich ein Objekt von anderen unterscheidet, können Sie _.reduce in Kombination mit _.isEqual und _.isPlainObject verwenden . In diesem Fall können Sie vergleichen, wie sich a von b unterscheidet oder wie sich b von a unterscheidet:

var a = {prop1: {prop1_1: 'text 1', prop1_2: 'text 2', prop1_3: [1, 2, 3]}, prop2: 2, prop3: 3};
var b = {prop1: {prop1_1: 'text 1', prop1_3: [1, 2]}, prop2: 2, prop3: 4};

var diff = function(obj1, obj2) {
  return _.reduce(obj1, function(result, value, key) {
    if (_.isPlainObject(value)) {
      result[key] = diff(value, obj2[key]);
    } else if (!_.isEqual(value, obj2[key])) {
      result[key] = value;
    }
    return result;
  }, {});
};

var res1 = diff(a, b);
var res2 = diff(b, a);
console.log(res1);
console.log(res2);
<script src="https://cdn.jsdelivr.net/npm/[email protected]/lodash.min.js"></script>

Santiago Bendavid
quelle
7

Einfache Verwendungsmethode _.isEqual, es funktioniert für alle Vergleiche ...

  • Hinweis: Diese Methode unterstützt das Vergleichen von Arrays, Array-Puffern, Booleschen Werten, * Datumsobjekten, Fehlerobjekten, Karten, Zahlen, ObjectObjekten, regulären Ausdrücken, * Mengen, Zeichenfolgen, Symbolen und typisierten Arrays. ObjectObjekte werden * anhand ihrer eigenen, nicht vererbten, aufzählbaren Eigenschaften verglichen. Funktionen und DOM * -Knoten werden nicht unterstützt.

Also, wenn Sie unten haben:

 const firstName = {name: "Alireza"};
 const otherName = {name: "Alireza"};

Wenn Sie das tun: _.isEqual(firstName, otherName);,

es wird wahr zurückgeben

Und wenn const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};

Wenn Sie das tun: _.isEqual(firstName, fullName);,

wird false zurückgeben

Alireza
quelle
6

Dieser Code gibt ein Objekt mit allen Eigenschaften zurück, die einen anderen Wert haben, sowie Werte beider Objekte. Nützlich, um den Unterschied zu protokollieren.

var allkeys = _.union(_.keys(obj1), _.keys(obj2));
var difference = _.reduce(allkeys, function (result, key) {
  if ( !_.isEqual(obj1[key], obj2[key]) ) {
    result[key] = {obj1: obj1[key], obj2: obj2[key]}
  }
  return result;
}, {});
blikblum
quelle
3

Ohne Verwendung von lodash / Unterstrich habe ich diesen Code geschrieben und arbeite gut für mich für einen tiefen Vergleich von Objekt1 mit Objekt2

function getObjectDiff(a, b) {
    var diffObj = {};
    if (Array.isArray(a)) {
        a.forEach(function(elem, index) {
            if (!Array.isArray(diffObj)) {
                diffObj = [];
            }
            diffObj[index] = getObjectDiff(elem, (b || [])[index]);
        });
    } else if (a != null && typeof a == 'object') {
        Object.keys(a).forEach(function(key) {
            if (Array.isArray(a[key])) {
                var arr = getObjectDiff(a[key], b[key]);
                if (!Array.isArray(arr)) {
                    arr = [];
                }
                arr.forEach(function(elem, index) {
                    if (!Array.isArray(diffObj[key])) {
                        diffObj[key] = [];
                    }
                    diffObj[key][index] = elem;
                });
            } else if (typeof a[key] == 'object') {
                diffObj[key] = getObjectDiff(a[key], b[key]);
            } else if (a[key] != (b || {})[key]) {
                diffObj[key] = a[key];
            } else if (a[key] == (b || {})[key]) {
                delete a[key];
            }
        });
    }
    Object.keys(diffObj).forEach(function(key) {
        if (typeof diffObj[key] == 'object' && JSON.stringify(diffObj[key]) == '{}') {
            delete diffObj[key];
        }
    });
    return diffObj;
}
Sridhar Gudimela
quelle
3

Tiefenvergleich mit einer Vorlage von (verschachtelten) Eigenschaften zur Überprüfung

function objetcsDeepEqualByTemplate(objectA, objectB, comparisonTemplate) {
  if (!objectA || !objectB) return false

  let areDifferent = false
  Object.keys(comparisonTemplate).some((key) => {
    if (typeof comparisonTemplate[key] === 'object') {
      areDifferent = !objetcsDeepEqualByTemplate(objectA[key], objectB[key], comparisonTemplate[key])
      return areDifferent
    } else if (comparisonTemplate[key] === true) {
      areDifferent = objectA[key] !== objectB[key]
      return areDifferent
    } else {
      return false
    }
  })

  return !areDifferent
}

const objA = { 
  a: 1,
  b: {
    a: 21,
    b: 22,
  },
  c: 3,
}

const objB = { 
  a: 1,
  b: {
    a: 21,
    b: 25,
  },
  c: true,
}

// template tells which props to compare
const comparisonTemplateA = {
  a: true,
  b: {
    a: true
  }
}
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateA)
// returns true

const comparisonTemplateB = {
  a: true,
  c: true
}
// returns false
objetcsDeepEqualByTemplate(objA, objB, comparisonTemplateB)

Dies funktioniert in der Konsole. Bei Bedarf kann Array-Unterstützung hinzugefügt werden

Pawel
quelle
2

Ich habe einen Adam Boduch-Code gestochen, um ein tiefes Diff auszugeben - dies ist völlig ungetestet, aber die Teile sind da:

function diff (obj1, obj2, path) {
    obj1 = obj1 || {};
    obj2 = obj2 || {};

    return _.reduce(obj1, function(result, value, key) {
        var p = path ? path + '.' + key : key;
        if (_.isObject(value)) {
            var d = diff(value, obj2[key], p);
            return d.length ? result.concat(d) : result;
        }
        return _.isEqual(value, obj2[key]) ? result : result.concat(p);
    }, []);
}

diff({ foo: 'lol', bar: { baz: true }}, {}) // returns ["foo", "bar.baz"]
Deminetix
quelle
1
Funktioniert wie ein Zauber, nur dass die Reihenfolge von obj1 und obj2 wichtig ist. Zum Beispiel: diff({}, { foo: 'lol', bar: { baz: true }}) // returns []
amangpt777
2

Wie es gefragt wurde, ist hier eine rekursive Objektvergleichsfunktion. Und ein bisschen mehr. Unter der Annahme, dass die primäre Verwendung einer solchen Funktion die Objektinspektion ist, habe ich etwas zu sagen. Ein vollständiger tiefer Vergleich ist eine schlechte Idee, wenn einige Unterschiede irrelevant sind. Zum Beispiel macht ein blinder tiefer Vergleich in TDD-Behauptungen Tests unnötig spröde. Aus diesem Grund möchte ich einen viel wertvolleren Teilunterschied einführen . Es ist ein rekursives Analogon eines früheren Beitrags zu diesem Thread. Schlüssel, die in a nicht vorhanden sind, werden ignoriert

var bdiff = (a, b) =>
    _.reduce(a, (res, val, key) =>
        res.concat((_.isPlainObject(val) || _.isArray(val)) && b
            ? bdiff(val, b[key]).map(x => key + '.' + x) 
            : (!b || val != b[key] ? [key] : [])),
        []);

Mit BDiff können Sie nach erwarteten Werten suchen und andere Eigenschaften tolerieren. Genau das möchten Sie für die automatische Überprüfung. Dies ermöglicht das Erstellen aller Arten von erweiterten Behauptungen. Zum Beispiel:

var diff = bdiff(expected, actual);
// all expected properties match
console.assert(diff.length == 0, "Objects differ", diff, expected, actual);
// controlled inequality
console.assert(diff.length < 3, "Too many differences", diff, expected, actual);

Zurück zur vollständigen Lösung. Das Erstellen eines vollständigen traditionellen Diff mit bdiff ist trivial:

function diff(a, b) {
    var u = bdiff(a, b), v = bdiff(b, a);
    return u.filter(x=>!v.includes(x)).map(x=>' < ' + x)
    .concat(u.filter(x=>v.includes(x)).map(x=>' | ' + x))
    .concat(v.filter(x=>!u.includes(x)).map(x=>' > ' + x));
};

Wenn Sie die obige Funktion für zwei komplexe Objekte ausführen, wird Folgendes ausgegeben:

 [
  " < components.0.components.1.components.1.isNew",
  " < components.0.cryptoKey",
  " | components.0.components.2.components.2.components.2.FFT.min",
  " | components.0.components.2.components.2.components.2.FFT.max",
  " > components.0.components.1.components.1.merkleTree",
  " > components.0.components.2.components.2.components.2.merkleTree",
  " > components.0.components.3.FFTResult"
 ]

Um einen Einblick in die Unterschiede zwischen den Werten zu erhalten, möchten wir möglicherweise die Diff-Ausgabe direkt auswerten () . Dafür benötigen wir eine hässlichere Version von bdiff , die syntaktisch korrekte Pfade ausgibt:

// provides syntactically correct output
var bdiff = (a, b) =>
    _.reduce(a, (res, val, key) =>
        res.concat((_.isPlainObject(val) || _.isArray(val)) && b
            ? bdiff(val, b[key]).map(x => 
                key + (key.trim ? '':']') + (x.search(/^\d/)? '.':'[') + x)
            : (!b || val != b[key] ? [key + (key.trim ? '':']')] : [])),
        []);

// now we can eval output of the diff fuction that we left unchanged
diff(a, b).filter(x=>x[1] == '|').map(x=>[x].concat([a, b].map(y=>((z) =>eval('z.' + x.substr(3))).call(this, y)))));

Das wird etwas Ähnliches ausgeben:

[" | components[0].components[2].components[2].components[2].FFT.min", 0, 3]
[" | components[0].components[2].components[2].components[2].FFT.max", 100, 50]

MIT-Lizenz;)

user46748
quelle
1

Um die Antwort von Adam Boduch zu vervollständigen, werden Unterschiede in den Eigenschaften berücksichtigt

const differenceOfKeys = (...objects) =>
  _.difference(...objects.map(obj => Object.keys(obj)));
const differenceObj = (a, b) => 
  _.reduce(a, (result, value, key) => (
    _.isEqual(value, b[key]) ? result : [...result, key]
  ), differenceOfKeys(b, a));
Ricardo Freitas
quelle
1

Wenn Sie nur einen Schlüsselvergleich benötigen:

 _.reduce(a, function(result, value, key) {
     return b[key] === undefined ? key : []
  }, []);
giuseppe
quelle
0

Hier ist ein einfaches Typoskript mit Lodash Deep Difference Checker, das ein neues Objekt mit nur den Unterschieden zwischen einem alten und einem neuen Objekt erzeugt.

Zum Beispiel, wenn wir hätten:

const oldData = {a: 1, b: 2};
const newData = {a: 1, b: 3};

Das resultierende Objekt wäre:

const result: {b: 3};

Es ist auch mit mehrstufigen tiefen Objekten kompatibel. Für Arrays müssen möglicherweise einige Anpassungen vorgenommen werden.

import * as _ from "lodash";

export const objectDeepDiff = (data: object | any, oldData: object | any) => {
  const record: any = {};
  Object.keys(data).forEach((key: string) => {
    // Checks that isn't an object and isn't equal
    if (!(typeof data[key] === "object" && _.isEqual(data[key], oldData[key]))) {
      record[key] = data[key];
    }
    // If is an object, and the object isn't equal
    if ((typeof data[key] === "object" && !_.isEqual(data[key], oldData[key]))) {
      record[key] = objectDeepDiff(data[key], oldData[key]);
    }
  });
  return record;
};
jmoore255
quelle
-1
var isEqual = function(f,s) {
  if (f === s) return true;

  if (Array.isArray(f)&&Array.isArray(s)) {
    return isEqual(f.sort(), s.sort());
  }
  if (_.isObject(f)) {
    return isEqual(f, s);
  }
  return _.isEqual(f, s);
};
Kreuzritter
quelle
Dies ist ungültig. Sie können Objekte nicht ===direkt mit vergleichen , es { a: 20 } === { a: 20 }wird false zurückgegeben, da der Prototyp verglichen wird. Der richtige Weg, um Objekte in erster Linie zu vergleichen, besteht darin, sie inJSON.stringify()
Herrgott
if (f === s) gibt true zurück; - ist nur zur Rekursion. Ja a: 20} === {a: 20} wird false zurückgeben und zur nächsten Bedingung übergehen
Crusader
warum nicht nur _.isEqual(f, s)? :)
Herrgott
Dies führt zu einer unendlichen Rekursionsschleife, denn wenn fes sich um ein Objekt handelt und Sie es erreichen, if (_.isObject(f))gehen Sie einfach durch die Funktion zurück und treffen Sie diesen Punkt erneut. Gleiches gilt fürf (Array.isArray(f)&&Array.isArray(s))
Rady
-2

Dies basierte auf @JLavoie unter Verwendung von lodash

let differences = function (newObj, oldObj) {
      return _.reduce(newObj, function (result, value, key) {
        if (!_.isEqual(value, oldObj[key])) {
          if (_.isArray(value)) {
            result[key] = []
            _.forEach(value, function (innerObjFrom1, index) {
              if (_.isNil(oldObj[key][index])) {
                result[key].push(innerObjFrom1)
              } else {
                let changes = differences(innerObjFrom1, oldObj[key][index])
                if (!_.isEmpty(changes)) {
                  result[key].push(changes)
                }
              }
            })
          } else if (_.isObject(value)) {
            result[key] = differences(value, oldObj[key])
          } else {
            result[key] = value
          }
        }
        return result
      }, {})
    }

https://jsfiddle.net/EmilianoBarboza/0g0sn3b9/8/

Emiliano Barboza
quelle
-2

nur mit Vanille js

let a = {};
let b = {};

a.prop1 = 2;
a.prop2 = { prop3: 2 };

b.prop1 = 2;
b.prop2 = { prop3: 3 };

JSON.stringify(a) === JSON.stringify(b);
// false
b.prop2 = { prop3: 2};

JSON.stringify(a) === JSON.stringify(b);
// true

Geben Sie hier die Bildbeschreibung ein

xgqfrms
quelle
1
Diese Methode würde Ihnen nicht sagen, welche Attribute unterschiedlich sind.
JLavoie
2
In diesem Fall beeinflussen die Attribute der Reihenfolge das Ergebnis.
Victor Oliveira
-2

Um auf der Antwort von Sridhar Gudimela aufzubauen , wird sie hier so aktualisiert, dass Flow glücklich wird:

"use strict"; /* @flow */



//  E X P O R T

export const objectCompare = (objectA: any, objectB: any) => {
  let diffObj = {};

  switch(true) {
    case (Array.isArray(objectA)):
      objectA.forEach((elem, index) => {
        if (!Array.isArray(diffObj))
          diffObj = [];

        diffObj[index] = objectCompare(elem, (objectB || [])[index]);
      });

      break;

    case (objectA !== null && typeof objectA === "object"):
      Object.keys(objectA).forEach((key: any) => {
        if (Array.isArray(objectA[key])) {
          let arr = objectCompare(objectA[key], objectB[key]);

          if (!Array.isArray(arr))
            arr = [];

          arr.forEach((elem, index) => {
            if (!Array.isArray(diffObj[key]))
              diffObj[key] = [];

            diffObj[key][index] = elem;
          });
        } else if (typeof objectA[key] === "object")
          diffObj[key] = objectCompare(objectA[key], objectB[key]);
        else if (objectA[key] !== (objectB || {})[key])
          diffObj[key] = objectA[key];
        else if (objectA[key] === (objectB || {})[key])
          delete objectA[key];
      });

      break;

    default:
      break;
  }

  Object.keys(diffObj).forEach((key: any) => {
    if (typeof diffObj[key] === "object" && JSON.stringify(diffObj[key]) === "{}")
      delete diffObj[key];
  });

  return diffObj;
};
NetOperator Wibby
quelle