比较两个 JavaScript 数组并删除重复条目。

3

我想要比较两个不同的数组,一个是之前的数据,一个是当前的数据。之前的数据集包含:

[
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"}
]

新的集合包含:

[
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"},
  {"member_name":"Test1","item":"Shield"}
]

您可以看到这里Test1获得了一个新的项目。我尝试过几种方法将这两个数组进行比较,但都没有成功。

我尝试过的方法:

这个方法只返回整个数组,而不是单个项目。

Items_Curr.filter(function(item) { return !Items_Prev.includes(item); });

这个方法只返回了 3 个 Undefined。
Items_Curr.map(e => { e.member_name });

我一直在寻找方法来完成这个任务,但其他帖子只是解释了如何确定较简单数组中的更改方法。
例如:[a,b] - [a, b, c]
更新:
最终目标是创建一个名为“NewItems”的新数组,其中包含所有新添加的名称和项目的数组。因此,如果有更改,我希望可以广播出来,如果没有更改,则忽略直到再次运行该函数。

你需要编写自己的比较方法。 - Shubham
我认为你的问题缺少一些信息。你想要什么样的输出?你希望它看起来像什么?比如说,你是想知道有什么新内容还是删除重复的内容? - Sinaesthetic
就像@Shubham所说的那样,您需要比较每个项目中的每个键值对,然后将唯一的项目推送到新数组中。 - Andria
1
没有所谓的JSON数组。JSON始终是一个字符串。您有一个对象数组。 - Mulan
还有,“unique”是什么?从技术上讲,两个数组中的所有3个对象都是独特的组合。 - Sinaesthetic
显示剩余2条评论
4个回答

5

实际上,你想要做的事情大概是这样的:

[a, b, c] - [a, b] 

这将给你带来c。您可以使用.some来实现这一点,它允许您“自定义”包含功能。

请查看下面的示例:

const arr1 = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"}
];

const arr2 = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"},
  {"member_name":"Test1","item":"Shield"}
];

const res = arr2.filter(({member_name:a, item:x}) => !arr1.some(({member_name:b, item:y}) => a === b && x === y));
console.log(res);


这也非常有效,我不知道您可以将{}元素添加到过滤器或某行中。 - T3rr11
@T3rr11 不用担心,这被称为解构赋值 - Nick Parsons

2

如果您知道属性始终会以相同的顺序出现,可以使用JSON.stringify对对象进行序列化并比较结果:

最初的回答:

如果您知道属性始终以相同的顺序出现,则可以使用JSON.stringify对对象进行序列化并比较结果:

const Items_Prev = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"}
]

const Items_Curr = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"},
  {"member_name":"Test1","item":"Shield"}
]

const serialized_Items_Prev = Items_Prev.map(i => JSON.stringify(i));
const NewItems = Items_Curr.filter(i => !serialized_Items_Prev.includes(JSON.stringify(i)));
console.log(NewItems);


1
如果对象的键不变,且只有新项目添加到最后,我认为您需要执行类似以下操作。

const array1 = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"}
];

const array2 = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"},
  {"member_name":"Test1","item":"Shield"}
];

const compare = (array1, array2) => {
 if (array1.length !== array2.length) {
   return false;
  }
  
  for (let i = 0; i < array1.length; i += 1) {
    if (array1[i].member_name !== array2[i].member_name) {
     return false;
    }
    
    if (array1[i].item !== array2[i].item) {
     return false;
    }
  }
  
  return true;
};

console.log(compare(array1, array2));

如果对象的顺序发生变化,那么您需要编写数组排序算法,然后进行比较。

数组项不按顺序排列怎么办? - brightDot
我觉得这是一个很好的答案,但对于更大的数组来说,它会产生相当大的负载,不是吗? - T3rr11
我也喜欢你比较数组长度的方法,这确实有助于提高性能! - T3rr11
@T3rr11会的。但是第一个答案只是比较字符串。如果顺序改变,就会出现问题。 - Shubham
@T3rr11 基本上是使用过滤器,有些人也在其中使用循环。所以我的答案只使用单个循环,并且循环一旦得到差异就会立即中断。这个函数看起来很大,但我认为它更有效率。 - Shubham
嗯,好的,我有点感觉到一些和过滤器是一样的,但使用它们会更加简洁。你的答案没有问题,看起来应该能够正常工作 :D - T3rr11

0

你可以使用数组方法filter()和findIndex()来实现它。

使用先前数组的findIndex()函数输出过滤当前数组。

var prevItems = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"}
]

var currItems = [
  {"member_name":"Test1","item":"Sword"},
  {"member_name":"Test2","item":"Sword"},
  {"member_name":"Test1","item":"Shield"},
  {"member_name":"Test2","item":"Shield"}
]

var newItems = currItems.filter(function(currItem ){
  return  prevItems.findIndex(function(prevItem){
     return prevItem.member_name ==  currItem.member_name &&
            prevItem.item == currItem.item
  }) == -1
})


console.log(newItems)


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