如何从对象数组中删除所有重复项?

2022-08-29 22:29:22

我有一个包含对象数组的对象。

obj = {};

obj.arr = new Array();

obj.arr.push({place:"here",name:"stuff"});
obj.arr.push({place:"there",name:"morestuff"});
obj.arr.push({place:"there",name:"morestuff"});

我想知道从数组中删除重复对象的最佳方法是什么。因此,例如,将变成...obj.arr

{place:"here",name:"stuff"},
{place:"there",name:"morestuff"}

答案 1

用一些魔法怎么样?es6

obj.arr = obj.arr.filter((value, index, self) =>
  index === self.findIndex((t) => (
    t.place === value.place && t.name === value.name
  ))
)

参考网址

更通用的解决方案是:

const uniqueArray = obj.arr.filter((value, index) => {
  const _value = JSON.stringify(value);
  return index === obj.arr.findIndex(obj => {
    return JSON.stringify(obj) === _value;
  });
});

使用上述属性策略而不是:JSON.stringify

const isPropValuesEqual = (subject, target, propNames) =>
  propNames.every(propName => subject[propName] === target[propName]);

const getUniqueItemsByProperties = (items, propNames) => 
  items.filter((item, index, array) =>
    index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNames))
  );

如果您希望属性是数组或值,则可以添加包装器:propNames

const getUniqueItemsByProperties = (items, propNames) => {
  const propNamesArray = Array.from(propNames);

  return items.filter((item, index, array) =>
    index === array.findIndex(foundItem => isPropValuesEqual(foundItem, item, propNamesArray))
  );
};

允许和getUniqueItemsByProperties('a')getUniqueItemsByProperties(['a']);

Stackblitz 示例

解释

  • 首先了解使用的两种方法:
  • 接下来,你的想法是什么使你的两个对象相等,并牢记这一点。
  • 我们可以将某些东西检测为重复项,如果它满足我们刚刚想到的标准,但它的位置不是在具有该标准的对象的第一个实例处。
  • 因此,我们可以使用上述标准来确定某些内容是否重复。

答案 2

一个带过滤器的衬垫(保留顺序)

在数组中查找唯一的 。id

arr.filter((v,i,a)=>a.findIndex(v2=>(v2.id===v.id))===i)

如果顺序不重要,地图解决方案将更快:使用地图解决


通过多个属性(和placename )

arr.filter((v,i,a)=>a.findIndex(v2=>['place','name'].every(k=>v2[k] ===v[k]))===i)

所有属性都是唯一的(对于大型数组,这将很慢)

arr.filter((v,i,a)=>a.findIndex(v2=>(JSON.stringify(v2) === JSON.stringify(v)))===i)

通过替换为 来保留最后一次出现的情况findIndexfindLastIndex

arr.filter((v,i,a)=>a.findLastIndex(v2=>(v2.place === v.place))===i)