2 वस्तुओं के बीच गहरी तुलना कैसे करें?


308

मेरे पास 2 नेस्टेड ऑब्जेक्ट हैं जो अलग-अलग हैं और मुझे यह जानने की जरूरत है कि क्या उनके नेस्टेड गुणों में से एक में अंतर है।

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

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

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

ऑब्जेक्ट अधिक नेस्टेड गुणों के साथ अधिक जटिल हो सकता है। लेकिन यह एक अच्छा उदाहरण है। मेरे पास पुनरावर्ती कार्यों या लॉश के साथ कुछ का उपयोग करने का विकल्प है ...


गहरी तुलना के लिए stackoverflow.com/a/46003894/696535
पावेल

7
_.isEqual(value, other)यह निर्धारित करने के लिए दो मूल्यों के बीच एक गहरी तुलना करता है कि क्या वे समकक्ष हैं। lodash.com/docs#isEqual
लुकास लाइज़िस

JSON.stringify ()
xgqfrms

10
JSON.stringify () गलत है: JSON.stringify ({a: 1, b: 2})! == JSON.stringify ({b: 2, a: 1})
Shl

जवाबों:


474

एक आसान और सुरुचिपूर्ण समाधान का उपयोग करना है _.isEqual, जो एक गहरी तुलना करता है:

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

हालाँकि, यह समाधान नहीं दिखाता है कि कौन सी संपत्ति अलग है।

http://jsfiddle.net/bdkeyn0h/


2
मुझे पता है कि उत्तर बहुत पुराना है, लेकिन मैं जोड़ना चाहता हूं, यह _.isEqualबहुत मुश्किल हो सकता है। यदि आप ऑब्जेक्ट को कॉपी करते हैं और वहां कुछ मान बदलते हैं तो यह अभी भी सही दिखाई देगा, क्योंकि संदर्भ समान है। तो इस फ़ंक्शन का उपयोग करके किसी को सावधान रहना चाहिए।
oruckdeschel

23
@oruckdeschel यदि संदर्भ समान है, तो यह एक ही वस्तु है। इसलिए यह बराबर है। यह एक संकेतक है जो मुश्किल नहीं है। लताश बहुत बढ़िया है।
आदमी मोगरबी

265

यदि आपको यह जानना होगा कि कौन से गुण अलग-अलग हैं, तो उपयोग कम करें () :

_.reduce(a, function(result, value, key) {
    return _.isEqual(value, b[key]) ?
        result : result.concat(key);
}, []);
// → [ "prop2" ]

36
ध्यान दें कि यह केवल पहले स्तर के विभिन्न गुणों का उत्पादन करेगा। (तो यह वास्तव में नहीं है गहरी गुण जो अलग हैं outputting के तौर पर।)
लड़का

16
इसके अलावा, यह उन गुणों को नहीं उठाएगा, जो बी में नहीं हैं।
एड स्टब

3
और _.reduce(a, (result, value, key) => _.isEqual(value, b[key]) ? result : result.concat(key), [])एक लाइन ES6 समाधान के लिए
Dotgreg

1
एक संस्करण concating कुंजी: मूल्यlet edited = _.reduce(a, function(result, value, key) { return _.isEqual(value, b[key]) ? result : result.concat( { [key]: value } ); }, []);
अलाइन माटोस

47

इस धागे पर ठोकर खाने वाले किसी भी व्यक्ति के लिए यहां एक अधिक संपूर्ण समाधान है। यह दो वस्तुओं की तुलना करेगा और आपको उन सभी गुणों की कुंजी देगा जो केवल ऑब्जेक्ट 1 में हैं , केवल ऑब्जेक्ट 2 में हैं , या ऑब्जेक्ट 1 और ऑब्जेक्ट 2 दोनों में हैं, लेकिन अलग-अलग मूल्य हैं :

/*
 * 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;
}

यहाँ एक उदाहरण आउटपुट है:

// 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"]

यदि आप नेस्टेड ऑब्जेक्ट्स के बारे में परवाह नहीं करते हैं और दर्ज करना छोड़ना चाहते हैं, तो आप _.isEqualसामान्य मूल्य की तुलना के लिए स्थानापन्न कर सकते हैं , जैसे obj1[key] === obj2[key]


यह चुना हुआ उत्तर सिर्फ समानता का परीक्षण करने के लिए सही है। यदि आपको यह जानने की आवश्यकता है कि अंतर क्या हैं, तो उन्हें सूचीबद्ध करने का कोई स्पष्ट तरीका नहीं है, लेकिन यह उत्तर बहुत अच्छा है, बस शीर्ष-स्तरीय संपत्ति कुंजियों की एक सूची दे रहा है जहां अंतर है। (और यह एक फ़ंक्शन के रूप में जवाब देता है, जो इसे प्रयोग करने योग्य बनाता है।)
सिगफ्रीड

ऐसा करने और केवल _.isEqual (obj1, obj2) का उपयोग करने में क्या अंतर है? HasOwnProperty के लिए चेक जोड़ने से क्या होता है कि _.isEqual नहीं करता है? मैं इस धारणा के तहत था कि अगर obj1 के पास एक संपत्ति है जो obj2 के पास नहीं है, _.isEqual सच नहीं होगा ..?
Jaked222

2
@ Jaked222 - अंतर यह है कि आइसकल एक बूलियन देता है जो आपको बताता है कि वस्तुएं समान हैं या नहीं, जबकि ऊपर दिया गया फ़ंक्शन आपको बताता है कि दोनों वस्तुओं के बीच क्या अंतर है (यदि वे अलग हैं)। यदि आप केवल यह जानने में रुचि रखते हैं कि दो वस्तुएं समान हैं, तो आइसक्वाल काफी पर्याप्त है। हालांकि कई मामलों में, आप जानना चाहते हैं कि दो वस्तुओं में क्या अंतर है। एक उदाहरण यह हो सकता है कि यदि आप किसी चीज़ से पहले और बाद में परिवर्तनों का पता लगाना चाहते हैं और फिर परिवर्तनों के आधार पर किसी घटना को भेजते हैं।
जोहान पर्सन

30

एडम बोडूच के जवाब के आधार पर , मैंने इस फ़ंक्शन को लिखा है जो दो वस्तुओं की तुलना सबसे गहरे संभव अर्थों में करता है , वापसी पथ जिसमें विभिन्न मूल्य हैं और साथ ही एक या दूसरी वस्तु से गायब होने वाले पथ हैं।

कोड को ध्यान में दक्षता के साथ नहीं लिखा गया था, और इस संबंध में सुधार सबसे स्वागत योग्य है, लेकिन यहां मूल रूप है:

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;
}

आप इस स्निपेट का उपयोग करके कोड आज़मा सकते हैं (पूर्ण पृष्ठ मोड में चलने की अनुशंसा की जाती है):


4
मैं सिर्फ बग को ठीक है, लेकिन आप किसी वस्तु में कुंजी अस्तित्व की जाँच करनी चाहिए आपको यह बताते हुए, b का उपयोग कर b.hasOwnProperty(key)याkey in b , के साथ नहीं b[key] != undefined। पुराने संस्करण के साथ जो प्रयोग किया जाता है b[key] != undefined, फ़ंक्शन ने ऑब्जेक्ट्स के लिए एक गलत अंतर लौटाया undefined, जैसे कि compare({disabled: undefined}, {disabled: undefined})। वास्तव में, पुराने संस्करण में भी समस्याएं थीं null; आप हमेशा का उपयोग करके इस तरह की समस्याओं से बचने कर सकते हैं ===और!== के बजाय ==और !=
रोरी ओ'केन

23

यहाँ एक संक्षिप्त समाधान है:

_.differenceWith(a, b, _.isEqual);

7
मेरे लिए वस्तुओं के साथ काम नहीं करता है। इसके बजाय एक खाली सरणी देता है।
टोमुघेस

2
लॉडश 4.17.4 के साथ खाली सरणी प्राप्त करना
aristidesfl

@ Z.Khullah अगर इस तरह से काम किया जाता है, तो यह प्रलेखित नहीं है।
ब्रेंडन

1
@Brendon, @THughes, @aristidesfl क्षमा करें, मैंने मिश्रित चीजें की हैं, यह वस्तुओं के सरणियों के साथ काम करता है, लेकिन गहरी वस्तु तुलना के लिए नहीं। जैसा कि यह पता चला है, अगर न तो पैरामीटर सरणियां हैं, तो लॉश बस वापस आ जाएगी []
जेड। खुल्ला

7

यह बताने के लिए कि कोई ऑब्जेक्ट अन्य के साथ कैसे अलग है आप _.reduce का उपयोग _.isEqual और _.isPlainObject के साथ कर सकते हैं । इस मामले में आप तुलना कर सकते हैं कि a, b से कैसे भिन्न है या b से कैसे भिन्न है:

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/lodash@4.17.4/lodash.min.js"></script>


7

सरल उपयोग _.isEqualविधि, यह सभी तुलना के लिए काम करेगा ...

  • नोट: यह विधि सरणियों, सरणी बफ़र्स, बूलियन, * दिनांक ऑब्जेक्ट, त्रुटि ऑब्जेक्ट, मैप, नंबर, Objectऑब्जेक्ट, regexes, * सेट, स्ट्रिंग्स, प्रतीक और टाइप किए गए सरणियों की तुलना करने का समर्थन करती है। Objectवस्तुओं की तुलना अपने स्वयं के द्वारा की जाती है, विरासत में नहीं, अनगिनत गुण। फ़ंक्शंस और DOM * नोड्स समर्थित नहीं हैं ।

तो अगर आप नीचे है:

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

यदि आप करते हैं: _.isEqual(firstName, otherName);,

यह सच हो जाएगा

और अगर const fullName = {firstName: "Alireza", familyName: "Dezfoolian"};

यदि आप करते हैं: _.isEqual(firstName, fullName);,

झूठा लौटेगा


6

यह कोड उन सभी गुणों के साथ एक वस्तु देता है, जिनका मूल्य अलग-अलग होता है और दोनों वस्तुओं के मूल्य भी। अंतर को लॉग करने के लिए उपयोगी है।

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;
}, {});

3

बिना लॉश / अंडरस्कोर के उपयोग के, मैंने इस कोड को लिखा है और ऑब्जेक्ट 2 के साथ ऑब्जेक्ट 1 की गहरी तुलना के लिए मेरे लिए ठीक काम कर रहा है

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;
}

3

डीप (नेस्टेड) ​​गुणों के टेम्प्लेट का उपयोग करके जाँच करने के लिए तुलना करें

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)

यह कंसोल में काम करेगा। यदि आवश्यक हो तो ऐरे समर्थन जोड़ा जा सकता है


2

मैंने एक स्टैड में एडम बोडुच के कोड को एक गहरे अंतर के उत्पादन के लिए लिया - यह पूरी तरह से अप्रयुक्त है लेकिन टुकड़े वहां हैं:

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"]

1
एक आकर्षण की तरह काम करता है, बस यह है कि obj1 और obj2 का क्रम महत्वपूर्ण है। उदाहरण के लिए: diff({}, { foo: 'lol', bar: { baz: true }}) // returns []
amangpt777

2

जैसा कि पूछा गया था, यहाँ एक पुनरावर्ती वस्तु तुलनात्मक कार्य है। और थोड़ा और। यह मानते हुए कि इस तरह के समारोह का प्राथमिक उपयोग वस्तु निरीक्षण है, मुझे कुछ कहना है। पूर्ण गहन तुलना एक बुरा विचार है जब कुछ अंतर अप्रासंगिक होते हैं। उदाहरण के लिए, टीडीडी अभिकथन में अंधा गहरी तुलना परीक्षणों को अनावश्यक भंगुर बना देती है। उस कारण से, मैं बहुत अधिक मूल्यवान आंशिक अंतर पेश करना चाहता हूं । यह इस धागे के लिए पिछले योगदान का एक पुनरावर्ती एनालॉग है। यह कुंजी में मौजूद नहीं है

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] : [])),
        []);

BDiff अन्य गुणों को सहन करते हुए अपेक्षित मूल्यों की जांच करने की अनुमति देता है, जो कि स्वचालित निरीक्षण के लिए आप चाहते हैं । यह सभी प्रकार के उन्नत अभिकथन के निर्माण की अनुमति देता है। उदाहरण के लिए:

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);

पूर्ण समाधान पर लौट रहे हैं। Bdiff के साथ एक पूर्ण पारंपरिक रूप का निर्माण तुच्छ है:

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));
};

दो जटिल वस्तुओं पर फ़ंक्शन के ऊपर चलने से यह कुछ समान होगा:

 [
  " < 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"
 ]

अंत में, मूल्यों में अंतर होने के बारे में एक झलक पाने के लिए, हम सीधे आउटपुट को अलग करना () कर सकते हैं । उसके लिए, हमें bdiff के एक बदसूरत संस्करण की आवश्यकता है जो कि वाक्यविन्यास को सही तरीके से आउटपुट करता है:

// 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)))));

यह इस तरह से कुछ उत्पादन होगा:

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

एमआईटी लाइसेंस;)


1

एडम बोडूच के जवाब को पूरा करते हुए, यह गुणों में अंतर लेता है

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));

1

यदि आपको केवल महत्वपूर्ण तुलना की आवश्यकता है:

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

0

यहाँ लोदश गहरे अंतर चेकर के साथ एक सरल टाइपस्क्रिप्ट है जो एक पुरानी वस्तु और एक नई वस्तु के बीच के अंतर के साथ एक नई वस्तु का उत्पादन करेगा।

उदाहरण के लिए, यदि हमारे पास था:

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

परिणामी वस्तु होगी:

const result: {b: 3};

यह बहु-स्तरीय गहरी वस्तुओं के साथ भी संगत है, सरणियों के लिए इसे कुछ ट्विकिंग की आवश्यकता हो सकती है।

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;
};

-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);
};

यह अमान्य है। आप ===सीधे वस्तुओं की तुलना नहीं कर सकते , { a: 20 } === { a: 20 }झूठे वापस आ जाएंगे, क्योंकि यह प्रोटोटाइप की तुलना करता है। मुख्य रूप से वस्तुओं की तुलना करने का अधिक सही तरीका हैJSON.stringify()
Herrgott

अगर (f === s) सही लौटा; - केवल पुनरावृत्ति के लिए है। हाँ a: 20} === {a: 20} झूठी वापस आ जाएगी और अगली स्थिति में जाएगी
क्रूसेडर

केवल क्यों नहीं _.isEqual(f, s)? :)
हेरगोट

यह एक अनंत पुनरावृत्ति लूप में परिणाम देगा, क्योंकि यदि fकोई वस्तु है और आप को if (_.isObject(f))बस समारोह के माध्यम से वापस जाने के लिए मिलता है और उस बिंदु को फिर से मारा। उसी के लिए जाता हैf (Array.isArray(f)&&Array.isArray(s))
rady

-2

यह @JLavoie पर आधारित था , जिसमें लॉश का उपयोग किया गया था

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/


-2

बस वेनिला जे एस का उपयोग कर

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

यहां छवि विवरण दर्ज करें


1
यह विधि आपको यह नहीं बताएगी कि कौन सी विशेषताएँ अलग हैं।
JLavoie

2
इस स्थिति में, गुण परिणाम में प्रभाव का आदेश देते हैं।
विक्टर ओलिवेरा

-2

श्रीधर गुडीमेला के उत्तर का निर्माण करने के लिए , यह इस तरह से अद्यतन किया गया है जो फ्लो को खुश कर देगा:

"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;
};
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.