比较两个对象数组

4
我有两个这样的数组。第一个数组是customFields,长度为2。
var customFields = [  
   {  
      "$$hashKey":"object:259",
      "fields":[  

      ],
      "id":0.84177744416334,
      "inputType":"number",
      "labelShown":"item",
      "type":"textBox",
      "value":"222222"
   },
   {  
      "$$hashKey":"object:260",
      "fields":[  
         "as",
         "dd",
         "asd"
      ],
      "id":0.51091342118417,
      "inputType":"",
      "labelShown":"labels",
      "type":"selectBox",
      "value":"dd"
   }
]

第二个是field,长度为3。
var field = [  
   {  
      "fields":[  

      ],
      "id":0.84177744416334,
      "inputType":"number",
      "labelShown":"item",
      "type":"textBox"
   },
   {  
      "fields":[  
         "as",
         "dd",
         "asd"
      ],
      "id":0.51091342118417,
      "inputType":"",
      "labelShown":"labels",
      "type":"selectBox"
   },
   {  
      "fields":[  

      ],
      "id":0.32625015743856,
      "inputType":"text",
      "labelShown":"sample",
      "type":"textBox"
   }
] 

这两个数组都是动态的,我需要通过 id 字段比较这些数组,并将缺失的对象从 field 数组添加到 customFields 数组中。如何在不使用嵌套循环的情况下完成这个操作?哪种方法最有效?谢谢!


1
基本上你无法使用单个迭代器来完成这个任务。无论你使用哪种迭代特性,你都需要嵌套方法来遍历嵌套结构。 - Teemu
对象是否总是按相同的顺序排列? - cbass
正如我所预料的那样,map和reduce的答案正在出现... :) 无论如何,在底层都会有循环。两个普通、明确的循环没有任何问题,以我个人的看法。 :) - sinisake
事实是数组可以包含大量对象,我担心比较和添加对象需要花费相当长的时间。 - Sachila Ranawaka
尝试使用lodash_.merge可以做到这一点,或者您可以与_.uniqBy结合使用。 - emaniacs
3个回答

7
您可以使用reduce()find()来获得所需的结果。

var customFields = [{"$$hashKey":"object:259","fields":[],"id":0.84177744416334,"inputType":"number","labelShown":"item","type":"textBox","value":"222222"},{"$$hashKey":"object:260","fields":["as","dd","asd"],"id":0.51091342118417,"inputType":"","labelShown":"labels","type":"selectBox","value":"dd"}];
var field = [{"fields":[],"id":0.84177744416334,"inputType":"number","labelShown":"item","type":"textBox"},{"fields":["as","dd","asd"],"id":0.51091342118417,"inputType":"","labelShown":"labels","type":"selectBox"},{"fields":[],"id":0.32625015743856,"inputType":"text","labelShown":"sample","type":"textBox"}]

var result = field.reduce(function(r, e) {
  var f = customFields.find(el => e.id == el.id)
  r.push(f ? f : e)
  return r;
}, [])

console.log(result)


谢谢兄弟。如果我理解正确,总值和当前值是从reduce方法传递的。但是你能否澄清一下find方法内部发生了什么? - Sachila Ranawaka
当然,它正在查找customFields中具有与field或e中当前元素相同的id的元素。如果找到它,它将返回该元素或在这种情况下返回其对象。 - Nenad Vracar
不错。这是我第一次看到在JavaScript中使用=>运算符赋值。毕竟,人生中第一次做任何事情都会有的。 - Sachila Ranawaka
这是ES6箭头函数,你可以用普通函数来替换它 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions - Nenad Vracar
让我们在聊天中继续这个讨论 - Sachila Ranawaka

1

0
这是一个没有嵌套循环的解决方案。首先生成一个查找表,其中包含“customFields”数组的ID。接下来遍历“field”数组,并将每个缺失的对象附加到“customFields”数组中。查找表也会更新以处理可能的重复项。
var lut = customFields.map(function(obj) {
  return obj.id;
});
field.forEach(function(obj) {
  if (lut.indexOf(obj.id) == -1) {
    customFields.push(obj);
    lut.push(obj.id);
  }
});

正如评论中所指出的,我的第一个建议在indexOf中隐藏了复杂性。

这里有一种替代方法,它依赖于对象属性进行ID查找,这可能比线性搜索更好。 lut维护了从ID到customFields数组索引的关联。

var lut = customFields.reduce(function(t, obj, i) {
  t[obj.id] = i;
  return t;
}, {});
field.forEach(function(obj) {
  if (undefined === lut[obj.id]) {
    lut[obj.id] = customFields.push(obj) - 1;
  }
});

如果customFields比fields更大会怎么样呢? - Legends
OP没有指定情况。这只是向customFields添加缺失的条目,而不考虑customFields中是否存在于field数组中不存在的条目。 - Joe
1
indexOf是这段代码中的嵌套迭代;)。 - Teemu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接