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

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

当前回答

可以将Object.values()与Array.prototype.reduce()结合使用:

const things=新对象();things.thing=新数组();thing.thing.push({place:“here”,name:“stuff”});things.thing.push({place:“there”,name:“morestuff”});things.thing.push({place:“there”,name:“morestuff”});constresult=Object.values(things.thing.reduce((a,c)=>(a[`${c.place}${c.name}`]=c,a),{}));console.log(结果);.作为控制台包装{最大高度:100%!重要;顶部:0;}

其他回答

在这里,我找到了一个使用reduce方法从对象数组中删除重复项的简单解决方案。我正在根据对象的位置键过滤元素

常量med=[{name:“name1”,位置:“left”},{name:“name2”,位置:“right”},{name:“name3”,位置:“left”},{name:“name4”,位置:“right”},{name:“name5”,位置:“left”},{name:“name6”,位置:“left1”}]常量arr=[];med.reduce((acc,curr)=>{如果(acc.indexOf(当前位置)==-1){acc.push(当前位置);arr.push(当前);}返回acc;}, [])控制台日志(arr)

您也可以使用地图:

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魔法怎么样?

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

如果您不介意以后对唯一数组进行排序,这将是一个有效的解决方案:

things.thing
  .sort(((a, b) => a.place < b.place)
  .filter((current, index, array) =>
    index === 0 || current.place !== array[index - 1].place)

这样,您只需将当前元素与数组中的前一个元素进行比较。在过滤之前排序一次(O(n*log(n))比在整个数组中搜索每个数组元素的重复项(O(n²))要便宜。

let data = [
  {
    'name': 'Amir',
    'surname': 'Rahnama'
  }, 
  {
    'name': 'Amir',
    'surname': 'Stevens'
  }
];
let non_duplicated_data = _.uniqBy(data, 'name');