簡體   English   中英

使用遞歸函數進行對象比較

[英]Objects comparison with recursive function

考慮以下函數的藍圖,該藍圖試圖比較兩個對象:

function objectCompare(a,b,path){ 
    for (var prop in a) {
      path=prop;
      if (a.hasOwnProperty(prop) && !(b.hasOwnProperty(prop))) {
                ...
          return false;
      }
      ...
      if (detectType(a[prop])==='Object'){
          if (!objectCompare(a[prop],b[prop],path)) 
               return false;
      }
      ...
    }
      return true;
}

detectType是我自己的函數,用於檢查變量的類型。 我的問題是,每次我們進行遞歸調用時,我都想豐富變量path 但是,在遞歸調用完成的同時, path必須遍歷初始對象的其余屬性名稱,而無需進行充實...想象以下對象:

var Obj1 = {
        p1: 's',
        p2: {
          p1: {a: { propA: 'a', propB: 'b' }},
          p2: 'g',
        }
      };

var Obj2 = {
        p1: 's',
        p2: {
          p1: {a: { propA: 'a', propB: 'c' }},
          p2: 'g',
        }
      };

我希望函數objectCompare返回時的path具有以下值: p2.p1.a.propB即,使兩個對象不同的點。 我該如何實現?

您必須將當前鍵添加到路徑,並將新路徑傳遞給遞歸調用。 考慮:

 console.info=function(x){document.write('<pre>'+JSON.stringify(x,0,3)+'</pre>')} //-- // compare: return path if a,b are different, null otherwise function compare(a, b, path) { var ta = typeof a, tb = typeof b; // different types - fail if (ta !== tb) { return path; } // scalars - null if equal, path if not if (ta !== 'object') { return a === b ? null : path; } // make a set of keys from both objects var keys = Object.keys(a).concat(Object.keys(b)).filter(function(x, i, self) { return self.indexOf(x) === i; }); // for each key in set, compare values var res = null; keys.some(function(k) { return res = compare(a[k], b[k], path.concat(k)); }); // return null or the first failed path return res; } // var Obj1 = { p1: 's', p2: { p1: {a: { propA: 'a', propB: 'b' }}, p2: 'g', } }; var Obj2 = { p1: 's', p2: { p1: {a: { propA: 'a', propB: 'c' }}, p2: 'g', } }; var res = compare(Obj1, Obj2, []) console.info(res); 

deep-diffdeep-diff您的需求。

上面的參考提供了以下示例代碼:

var diff = require('deep-diff').diff;

var lhs = {
    name: 'my object',
    description: 'it\'s an object!',
    details: {
        it: 'has',
        an: 'array',
        with: ['a', 'few', 'elements']
    }
};

var rhs = {
    name: 'updated object',
    description: 'it\'s an object!',
    details: {
        it: 'has',
        an: 'array',
        with: ['a', 'few', 'more', 'elements', { than: 'before' }]
    }
};

var differences = diff(lhs, rhs);

上面的代碼段將導致以下結構描述差異:

[ { kind: 'E',
    path: [ 'name' ],
    lhs: 'my object',
    rhs: 'updated object' },
  { kind: 'E',
    path: [ 'details', 'with', 2 ],
        lhs: 'elements',
        rhs: 'more' },
  { kind: 'A',
    path: [ 'details', 'with' ],
    index: 3,
    item: { kind: 'N', rhs: 'elements' } },
  { kind: 'A',
    path: [ 'details', 'with' ],
    index: 4,
    item: { kind: 'N', rhs: { than: 'before' } } } ]

值得注意的是, path屬性非常類似於您所需的輸出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM