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

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和Array.reduce与Array.find一起使用。在此示例中,根据guid属性筛选对象。

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

扩展此选项以允许选择属性并将其压缩为一行:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

要使用它,请将对象数组和要进行重复数据消除的键的名称作为字符串值传递:

const result = uniqify(myArrayOfObjects, 'guid')

其他回答

另一种方法是使用reduce函数,并使用一个新数组作为累加器。如果累加器数组中已经有一个同名的对象,那么不要将其添加到那里。

let list = things.thing;
list = list.reduce((accumulator, thing) => {
    if (!accumulator.filter((duplicate) => thing.name === duplicate.name)[0]) {
        accumulator.push(thing);
    }
    return accumulator;
}, []);
thing.things = list;

我添加了这个答案,因为我找不到与InternetExplorer11兼容的好的、可读的es6解决方案(我使用babel来处理箭头函数)。问题是IE11没有没有polyfill的Map.values()或Set.values)。出于同样的原因,我使用filter()[0]来获取第一个元素,而不是find()。

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

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

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 obj = {};

for (let i = 0, len = things.thing.length; i < len; i++) {
  obj[things.thing[i]['place']] = things.thing[i];
}

things.thing = new Array();

 for (const key in obj) { 
   things.thing.push(obj[key]);
}

向列表中再添加一个。将ES6和Array.reduce与Array.find一起使用。在此示例中,根据guid属性筛选对象。

let filtered = array.reduce((accumulator, current) => {
  if (! accumulator.find(({guid}) => guid === current.guid)) {
    accumulator.push(current);
  }
  return accumulator;
}, []);

扩展此选项以允许选择属性并将其压缩为一行:

const uniqify = (array, key) => array.reduce((prev, curr) => prev.find(a => a[key] === curr[key]) ? prev : prev.push(curr) && prev, []);

要使用它,请将对象数组和要进行重复数据消除的键的名称作为字符串值传递:

const result = uniqify(myArrayOfObjects, 'guid')

另一个选项是创建一个自定义indexOf函数,该函数比较每个对象所选属性的值,并将其包装在reduce函数中。

var uniq = redundant_array.reduce(function(a,b){
      function indexOfProperty (a, b){
          for (var i=0;i<a.length;i++){
              if(a[i].property == b.property){
                   return i;
               }
          }
         return -1;
      }

      if (indexOfProperty(a,b) < 0 ) a.push(b);
        return a;
    },[]);