检查JavaScript中两个对象数组之间的差异

14
我需要帮忙。在这种情况下,如何获取差异的数组?
var b1 = [
  { id: 0, name: 'john' }, 
  { id: 1, name: 'mary' }, 
  { id: 2, name: 'pablo' }, 
  { id: 3, name: 'escobar' } 
]; 

var b2 = [
  { id: 0, name: 'john' }, 
  { id: 1, name: 'mary' }
];

我想要差异的数组:
// [{ id: 2, name: 'pablo' }, { id: 3, name: 'escobar' }]

“最优化的方法是什么?”
“我正在尝试过滤一个缩小的数组.. 大致是这样的:”
var Bfiltered = b1.filter(function (x) {
return x.name !== b2.reduce(function (acc, document, index) {
    return (document.name === x.name) ? document.name : false
},0)

});

console.log("Bfiltered", Bfiltered);
// returns { id: 0, name: 'john' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ]

谢谢,机器人

1
不确定为什么你的问题会被踩,因为你已经更新了问题并发布了格式良好的帖子。我给你点赞。 - Ryan Wilson
@RyanWilson,所以你是那些为平均时间复杂度为O(mn)的问题解决方案点赞的人之一,而这些问题最好只能达到O(max(m, n)),并且这些问题已经被问了无数次(尽管顶部也有O(mn)的解决方案)。 - ASDFGerte
1
@ASDFGerte 我是那种欣赏一个人愿意学习并试图解决编程问题的人。 - Ryan Wilson
@RyanWilson 谷歌可能记住了我的过去搜索记录,但是我给出的重复链接是在不改变任何字母的情况下,将此问题的标题复制后给出的第一个结果。 - ASDFGerte
1
虽然我同意这个问题可能可以被OP更好地搜索,但他们显然对这个网站还比较新,所以我倾向于对新人更宽容,而不是那些长期来到这个网站的人。我想我是那些喜欢鼓励人而不是批评的“软心肠”。 - Ryan Wilson
3个回答

40
.Filter().some()函数会解决问题。

var b1 = [
  { id: 0, name: 'john' }, 
  { id: 1, name: 'mary' }, 
  { id: 2, name: 'pablo' }, 
  { id: 3, name: 'escobar' } 
]; 

var b2 = [
  { id: 0, name: 'john' }, 
  { id: 1, name: 'mary' }
];

var res = b1.filter(item1 => 
!b2.some(item2 => (item2.id === item1.id && item2.name === item1.name)))

console.log(res);


2
只是一个可能的补充,先检查哪个数组长度更大,然后再进行过滤。否则,我同意加1。 - Ryan Wilson
我怎样才能只返回true或false而不是项目? - Oliver D
@OliverD 也许是 res.length > 0 吗? - Chiller

8
您可以使用filter来筛选/循环遍历数组,并使用some检查数组2中是否存在id。

var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ]; 
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];

var result = b1.filter(o => !b2.some(v => v.id === o.id));

console.log(result);


如果数组1较长,上面的示例将起作用。如果您不知道哪个更长,可以使用sort来排列数组,并使用reducefilter

var b1 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }, { id: 2, name: 'pablo' }, { id: 3, name: 'escobar' } ]; 
var b2 = [{ id: 0, name: 'john' }, { id: 1, name: 'mary' }];

var result = [b1, b2].sort((a,b)=> b.length - a.length)
                     .reduce((a,b)=>a.filter(o => !b.some(v => v.id === o.id)));

console.log(result);


1
仅仅是一个可能的补充,先检查哪个数组长度更大,再进行过滤。否则,我还是赞同加1。 - Ryan Wilson
谢谢,今天通过你的示例我学到了新东西,以前从未使用过 .some()。另外,你的第二个示例非常棒,ESMAScript6 的箭头函数让我大开眼界!;) - Ryan Wilson
我怎样才能只返回True或False而不是其他的项目? - Oliver D

0
另一种可能性是使用Map,这样可以将时间复杂度降低到O(max(n,m)),如果使用Map结果对您来说没问题的话。

function findArrayDifferences(arr1, arr2) {
const map = new Map();
const maxLength = Math.max(arr1.length, arr2.length);
for (let i = 0; i < maxLength; i++) {
 if (i < arr1.length) {
  const entry = arr1[i];
  if (map.has(entry.id)) {
   map.delete(entry.id);
  } else {
   map.set(entry.id, entry);
  }

 }
 if (i < arr2.length) {
  const entry = arr2[i];
  if (map.has(entry.id)) {
   map.delete(entry.id);
  } else {
   map.set(entry.id, entry);
  }

 }
}
return map;
}

const arr1 = [{id:0,name:'john'},{id:1,name:'mary'},{id:2,name:'pablo'},{id:3,name:'escobar'}];
const arr2 = [{id:0,name:'john'},{id:1,name:'mary'},{id:99,name:'someone else'}];
const resultAsArray = [...findArrayDifferences(arr1,arr2).values()];
console.log(resultAsArray);


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