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

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"}

当前回答

在一行中使用ES6+,您可以按键获得唯一的对象列表:

const key = 'place';
const unique = [...new Map(arr.map(item => [item[key], item])).values()]

可以将其放入函数中:

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

下面是一个工作示例:

常量arr=[{地点:“这里”,名称:“x”,其他:“其他stuff1”},{地点:“那里”,名称:“x”,其他:“其他stuff2”},{地点:“这里”,名称:“y”,其他:“其他stuff4”},{地点:“这里”,名称:“z”,其他:“其他stuff5”}]函数getUniqueListBy(arr,key){return[…new Map(arr.Map(item=>[item[key],item])).values()]}const arr1=getUniqueListBy(arr,'place')console.log(“按位置唯一”)console.log(JSON.stringify(arr1))console.log(“\n名称唯一”)const arr2=getUniqueListBy(arr,'name')console.log(JSON.stringify(arr2))

它是如何工作的

首先,以可以用作Map输入的方式重新映射数组。

arr.map(项=>[项[键],项]);

这意味着阵列的每个项目将被转换为具有2个元素的另一个阵列;选定的键作为第一个元素,整个初始项作为第二个元素,这称为条目(例如数组条目、映射条目)。这是一个官方文档,其中有一个示例显示了如何在Map构造函数中添加数组项。

放置钥匙时的示例:

[["here", {place: "here",  name: "x", other: "other stuff1" }], ...]

其次,我们将这个修改后的数组传递给Map构造函数,这就是神奇的发生。映射将消除重复的关键字值,只保留同一关键字的最后插入值。注意:贴图保持插入顺序。(检查贴图和对象之间的差异)

新映射(上面刚刚映射的条目数组)

第三,我们使用map值来检索原始项,但这次没有重复项。

新映射(mappedArr).values()

最后一个是将这些值添加到一个新的数组中,这样它可以看起来像初始结构,并返回:

return[…new Map(mappedArr).values()]

其他回答

TypeScript解决方案

这将删除重复的对象,并保留对象的类型。

function removeDuplicateObjects(array: any[]) {
  return [...new Set(array.map(s => JSON.stringify(s)))]
    .map(s => JSON.parse(s));
}

来点es6魔法怎么样?

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

参考URL

更通用的解决方案是:

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))
  );
};

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

Stackblitz示例

解释

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

您也可以使用地图:

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

完整样本:

const things = new Object();

things.thing = new Array();

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

const dedupThings = Array.from(things.thing.reduce((m, t) => m.set(t.place, t), new Map()).values());

console.log(JSON.stringify(dedupThings, null, 4));

结果:

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

这里是ES6的解决方案,您只想保留最后一项。该解决方案功能强大,符合Airbnb风格。

const things = {
  thing: [
    { place: 'here', name: 'stuff' },
    { place: 'there', name: 'morestuff1' },
    { place: 'there', name: 'morestuff2' }, 
  ],
};

const removeDuplicates = (array, key) => {
  return array.reduce((arr, item) => {
    const removed = arr.filter(i => i[key] !== item[key]);
    return [...removed, item];
  }, []);
};

console.log(removeDuplicates(things.thing, 'place'));
// > [{ place: 'here', name: 'stuff' }, { place: 'there', name: 'morestuff2' }]

任何对象数组的泛型:

/**
* Remove duplicated values without losing information
*/
const removeValues = (items, key) => {
  let tmp = {};

  items.forEach(item => {
    tmp[item[key]] = (!tmp[item[key]]) ? item : Object.assign(tmp[item[key]], item);
  });
  items = [];
  Object.keys(tmp).forEach(key => items.push(tmp[key]));

  return items;
}

希望这对任何人都有帮助。