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

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

当前回答

这是如何从对象数组中删除重复性的简单方法。

我经常处理数据,这对我很有用。

const data = [{name: 'AAA'}, {name: 'AAA'}, {name: 'BBB'}, {name: 'AAA'}];
function removeDuplicity(datas){
    return datas.filter((item, index,arr)=>{
    const c = arr.map(item=> item.name);
    return  index === c.indexOf(item.name)
  })
}

console.log(removeDuplicity(data))

将打印到控制台:

[[object Object] {
name: "AAA"
}, [object Object] {
name: "BBB"
}]

其他回答

您可以将数组对象转换为字符串,以便对其进行比较,将字符串添加到集合中,以便自动删除可比较的重复项,然后将每个字符串转换回对象。

它可能不像其他答案那样有表现力,但它是可读的。

const things = {};

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

const uniqueArray = (arr) => {

  const stringifiedArray = arr.map((item) => JSON.stringify(item));
  const set = new Set(stringifiedArray);

  return Array.from(set).map((item) => JSON.parse(item));
}

const uniqueThings = uniqueArray(things.thing);

console.log(uniqueThings);

如果您发现需要经常基于特定字段从数组中删除重复的对象,那么创建一个可以从项目中任何位置导入的独特(数组、谓词)函数可能是值得的。这看起来像

const things = [{place:"here",name:"stuff"}, ...];
const distinctThings = distinct(things, thing => thing.place);

不同的函数可以使用上面许多好答案中给出的任何实现。最简单的方法是使用findIndex:

const distinct = (items, predicate) => items.filter((uniqueItem, index) =>
    items.findIndex(item =>
        predicate(item) === predicate(uniqueItem)) === index);

你听说过洛达什图书馆吗?当您不想将逻辑应用于代码时,我建议您使用此实用程序,并使用已优化且可靠的现有代码。

考虑制作一个这样的数组

things.thing.push({place:"utopia",name:"unicorn"});
things.thing.push({place:"jade_palace",name:"po"});
things.thing.push({place:"jade_palace",name:"tigress"});
things.thing.push({place:"utopia",name:"flying_reindeer"});
things.thing.push({place:"panda_village",name:"po"});

注意,如果您想保持一个属性的唯一性,您可以使用lodash库来实现这一点。在这里,您可以使用_.uniqBy

.uniqBy(数组,[iteratee=.identity])

此方法类似于_.uniq(它返回一个数组的无重复版本,其中只保留每个元素的第一次出现),只是它接受iterate,iterate为数组中的每个元素调用,以生成计算唯一性的标准。

因此,例如,如果要返回具有唯一属性“place”的数组

_.uniqBy(things.thing,'place')

同样,如果您希望唯一属性为“name”

_.uniqBy(things.thing,'name')

希望这有帮助。

干杯

这里是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' }]

来点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接下来,让你的想法让你的两个对象相等,并记住这一点。如果某个东西满足我们刚刚想到的标准,我们可以将其检测为复制品,但它的位置不在具有该标准的对象的第一个实例处。因此,我们可以使用上述标准来确定某个东西是否是重复的。