当前位置:  开发笔记 > 编程语言 > 正文

如何获取两个JavaScript对象图之间的差异列表?

如何解决《如何获取两个JavaScript对象图之间的差异列表?》经验,为你挑选了4个好方法。

我希望能够获得两个JavaScript对象图之间所有差异的列表,以及发生增量的属性名称和值.

对于它的价值,这些对象通常作为JSON从服务器中检索,并且通常只有少数深层(即它可能是一个对象数组,它们本身具有数据,然后是与其他数据对象一起的数组).

我想不仅要看到基本属性的更改,还要看到数组成员数量的差异等.

如果我没有得到答案,我可能最终会自己写这篇文章,但希望有人已经完成了这项工作或者知道有人.


编辑:这些对象通常在结构上彼此非常接近,所以我们不是在讨论彼此完全不同的对象,而是可能有3或4个增量.



1> Jason Buntin..:

这是我的问题的一个部分,天真的解决方案 - 我将在我进一步开发它时更新它.

function findDifferences(objectA, objectB) {
   var propertyChanges = [];
   var objectGraphPath = ["this"];
   (function(a, b) {
      if(a.constructor == Array) {
         // BIG assumptions here: That both arrays are same length, that
         // the members of those arrays are _essentially_ the same, and 
         // that those array members are in the same order...
         for(var i = 0; i < a.length; i++) {
            objectGraphPath.push("[" + i.toString() + "]");
            arguments.callee(a[i], b[i]);
            objectGraphPath.pop();
         }
      } else if(a.constructor == Object || (a.constructor != Number && 
                a.constructor != String && a.constructor != Date && 
                a.constructor != RegExp && a.constructor != Function &&
                a.constructor != Boolean)) {
         // we can safely assume that the objects have the 
         // same property lists, else why compare them?
         for(var property in a) {
            objectGraphPath.push(("." + property));
            if(a[property].constructor != Function) {
               arguments.callee(a[property], b[property]);
            }
            objectGraphPath.pop();
         }
      } else if(a.constructor != Function) { // filter out functions
         if(a != b) {
            propertyChanges.push({ "Property": objectGraphPath.join(""), "ObjectA": a, "ObjectB": b });
         }
      }
   })(objectA, objectB);
   return propertyChanges;
}

这里有一个如何使用它和它将提供的数据的样本(请原谅长的例子,但我想使用一些相对非平凡的东西):

var person1 = { 
   FirstName : "John", 
   LastName : "Doh", 
   Age : 30, 
   EMailAddresses : [
      "john.doe@gmail.com", 
      "jd@initials.com"
   ], 
   Children : [ 
      { 
         FirstName : "Sara", 
         LastName : "Doe", 
         Age : 2 
      }, { 
         FirstName : "Beth", 
         LastName : "Doe", 
         Age : 5 
      } 
   ] 
};

var person2 = { 
   FirstName : "John", 
   LastName : "Doe", 
   Age : 33, 
   EMailAddresses : [
      "john.doe@gmail.com", 
      "jdoe@hotmail.com"
   ], 
   Children : [ 
      { 
         FirstName : "Sara", 
         LastName : "Doe", 
         Age : 3 
      }, { 
         FirstName : "Bethany", 
         LastName : "Doe", 
         Age : 5 
      } 
   ] 
};

var differences = findDifferences(person1, person2);

此时,differences如果将序列化为JSON ,则数组的外观如下:

[
   {
      "Property":"this.LastName", 
      "ObjectA":"Doh", 
      "ObjectB":"Doe"
   }, {
      "Property":"this.Age", 
      "ObjectA":30, 
      "ObjectB":33
   }, {
      "Property":"this.EMailAddresses[1]", 
      "ObjectA":"jd@initials.com", 
      "ObjectB":"jdoe@hotmail.com"
   }, {
      "Property":"this.Children[0].Age", 
      "ObjectA":2, 
      "ObjectB":3
   }, {
      "Property":"this.Children[1].FirstName", 
      "ObjectA":"Beth", 
      "ObjectB":"Bethany"
   }
]

thisProperty值是指被比较的对象的根.因此,该解决方案还没有正是我所需要的,但它是相当的接近.

希望这对那里的人有用,如果你有任何改进的建议,我全心全意; 我昨晚很晚才写到这个(即今天凌晨),我可能会完全忽视这些事情.

谢谢.


伙计们,请注意:ES5 arguments.callee在严格模式下被禁止.https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/callee

2> ryanm..:

在查看现有答案后,我注意到https://github.com/flitbit/diff库尚未列为解决方案.

从我的研究来看,这个库在积极开发,贡献和分叉方面似乎是最好的,可以解决差异对象的挑战.这对于在服务器端创建差异并仅向客户端传递更改的位非常方便.



3> anton_byrna..:

有一个objectDiff库,允许您这样做.在其演示页面上,您可以看到两个javascript对象之间的差异.



4> Mirek Rusin..:

您还可以尝试rus-diff https://github.com/mirek/node-rus-diff,它会生成MongoDB兼容(重命名/取消设置/设置)差异.

对于您的示例对象:

var person1 = {
  FirstName: "John",
  LastName: "Doh",
  Age: 30,
  EMailAddresses: ["john.doe@gmail.com", "jd@initials.com"],
  Children: [
    {
      FirstName: "Sara",
      LastName: "Doe",
      Age: 2
    }, {
      FirstName: "Beth",
      LastName: "Doe",
      Age: 5
    }
  ]
};

var person2 = {
  FirstName: "John",
  LastName: "Doe",
  Age: 33,
  EMailAddresses: ["john.doe@gmail.com", "jdoe@hotmail.com"],
  Children: [
    {
      FirstName: "Sara",
      LastName: "Doe",
      Age: 3
    }, {
      FirstName: "Bethany",
      LastName: "Doe",
      Age: 5
    }
  ]
};

var rusDiff = require('rus-diff').rusDiff

console.log(rusDiff(person1, person2))

它会生成一组集:

{ '$set': 
   { 'Age': 33,
     'Children.0.Age': 3,
     'Children.1.FirstName': 'Bethany',
     'EMailAddresses.1': 'jdoe@hotmail.com',
     'LastName': 'Doe' } }

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有