【问题标题】:How to find differences between two JavaScript arrays of objects?如何找到两个 JavaScript 对象数组之间的差异?
【发布时间】:2016-12-28 16:53:16
【问题描述】:

我有两个 JavaScript 数组 orig(原始对象数组)和 update(更新后的原始对象数组),它们具有相同的长度并包含对象,我想输出每对之间的差异对象。

例子:

var orig = [{enabled:"true", name:"Obj1", id:3},{enabled:"true", name:"Obj2", id:4}]; 

var update = [{enabled:"true", name:"Obj1", id:3}, {enabled:"true", name:"Obj2-updated", id:4}];

输出应该是:name:"Obj2-updated"

我实现了一些东西,但它需要优化......

for(var prop=0; prop<orig.length; prop++) {
  for(prop=0; prop<update.length; prop++) {
    if(orig[prop].enabled != update.enabled) { console.log(update.enabled) }
    if(orig[prop].name != update[prop].name) { console.log(update[prop].name) }
    if(orig[prop].id != update[prop].id) { console.log(update[prop].id) }
  }
}

【问题讨论】:

  • 输出是字符串还是对象?或者一个带有对象或字符串的数组,或者?
  • 虽然我不知道您的用例,但对我来说,只有一个已更改值的列表似乎没有用,而不知道更改值存在于哪个键和哪个对象中;你确定你不需要更多细节吗?我并不是要贬低您的问题,而是要预测您的下一个问题可能是什么,如果您只需要更改的值是错误的。
  • 我只需要该输出来创建一个字符串文本,上面写着:“嘿,你将 Obj2 更改为 Obj2-updated”。但我只需要知道修改了哪个属性。
  • @NinaScholz 输出是字符串还是对象都没关系。
  • 我投票结束这个问题,因为对于那些试图回答的人来说,它是一个不断变化的目标。在问一个问题之前,先花点时间弄清楚你到底想要什么。检查您发布的输入是否准确(要比较的对象数组,而不仅仅是两个不同的对象),并且您知道需要什么结果,无论是更改值,更改值 和 i> 该值的键,或具有更改值的整个对象;十分钟可以为所有人节省时间。

标签: javascript arrays javascript-objects difference data-manipulation


【解决方案1】:

您可以过滤键并使用更新后的键获得结果集。

var orig = [{ enabled: "true", name: "Obj1", id: 3 }, { enabled: "true", name: "Obj2", id: 4 }],
    update = [{ enabled: "true", name: "Obj1", id: 3 }, { enabled: "true", name: "Obj2-updated", id: 4 }],
    difference = [];

orig.forEach(function (a, i) {
    Object.keys(a).forEach(function (k) {
        if (a[k] !== update[i][k]) {
            difference.push({ id: update[i].id, key: k, value: update[i][k], index: i });
        }
    });
});

console.log(difference);

【讨论】:

  • 能否告诉我是否有办法记录修改后的对象?在这种情况下{ enabled: "true", name: "Obj2-updated", id: 4 }
  • 你看,这就是为什么I asked you, earlier, if you're sure you only needed the changed value。到目前为止,问题已经改变,所需的返回值已经改变,从只是改变的值,到改变的值该值的键和现在你'已经决定要返回整个修改后的对象。请在提出问题之前花五分钟时间来正确地撰写问题。
  • @PavelValeriu,如果我知道,如何结果应该是什么样子,我可以给出答案。那你需要什么?对象,或索引或键/值对或什么?
  • @PavelValeriu:当然有可能。只需仔细查看 Nina 的解决方案在做什么,在调试器中一步一步地进行操作,您就可以弄清楚如何做到这一点。
【解决方案2】:

假设两者的属性名称相同并且值只是原始值(没有对象、数组等):

Object.keys( orig )
      .forEach( (key) => {
        if( orig[ key ] !== update[ key ] ) {
          console.log( update[key] );
        }
      });

【讨论】:

  • 我可以使用orig[prop][key] 吗?
  • @PavelValeriu 做什么?在您的示例代码中,您假设两个变量都包含数组,但它们实际上是对象。所以你的.length 实际上不应该工作(除非你明确地设置它)
  • 不值得我发布一个单独的答案,因为它本质上是相同的,但是由于 OP 只想知道哪些值是不同的(显然不参考键),所以更容易使用Object.values(),而不是在每次迭代时通过键访问对象的值(这确实需要在浏览器中实现Object.values(),但显然)。
  • @DavidThomas 出于好奇:您如何使用Object.values() 将值相互匹配,而无需访问相应的键?
  • @Sirko 抱歉,我的 origupdate 是包含对象的数组,我会更新我的问题
【解决方案3】:

使用Object.keys 循环浏览您的对象。比如:

var orig = {
  enabled: "true",
  name: "Obj1",
  id: 3
};

var update = {
  enabled: "true",
  name: "Obj1-updated",
  id: 3
};

var diff = {};

Object.keys(orig).forEach(function(key) {
  if (orig[key] != update[key]) {
    diff[key] = update[key];
  };
})

console.log(diff);

【讨论】:

    【解决方案4】:

    您可以使用单个循环遍历原始对象的属性并检查更新后的对象以找出哪些属性已被修改。

    var orig = {
      enabled: "true",
      name: "Obj1",
      id: 3
    };
    
    var update = {
      enabled: "true",
      name: "Obj1-updated",
      id: 3
    };
    
    for (var key in orig) {
      if (orig[key] !== update[key]) {
        console.log(key + ': ' + update[key]);
      }
    }

    【讨论】:

      【解决方案5】:

      您可以使用 lodash 或 Ramda 之类的库以简洁的方式进行操作。在 Ramda 的情况下,你可以这样做: R.difference(update, orig);

      【讨论】:

        猜你喜欢
        • 2022-01-04
        • 1970-01-01
        • 1970-01-01
        • 2014-03-26
        • 2019-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多