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

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

当前回答

另一种方法是使用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()。

其他回答

这是一种通用的方法:传入一个函数,该函数测试数组的两个元素是否相等。在本例中,它比较所比较的两个对象的名称和位置财产的值。

ES5答案

函数removeDucplicates(arr,equals){var originalArr=arr.slice(0);变量i,len,val;arr.length=0;对于(i=0,len=原始Arr.length;i<len;++i){val=原始Arr[i];if(!arr.some(函数(项){return equals(项,val);})){arr.push(val);}}}函数thingsEqual(thing1,thing2){返回thing1.place==thing2.place&&thing.name===thing.name;}var事物=[{地点:“这里”,名称:“东西”},{地点:“there”,名称:“morestuff”},{地点:“there”,名称:“morestuff”}];删除重复项(things,thingsEqual);console.log(things);

ES3原始答案

function arrayContains(arr, val, equals) {
    var i = arr.length;
    while (i--) {
        if ( equals(arr[i], val) ) {
            return true;
        }
    }
    return false;
}

function removeDuplicates(arr, equals) {
    var originalArr = arr.slice(0);
    var i, len, j, val;
    arr.length = 0;

    for (i = 0, len = originalArr.length; i < len; ++i) {
        val = originalArr[i];
        if (!arrayContains(arr, val, equals)) {
            arr.push(val);
        }
    }
}

function thingsEqual(thing1, thing2) {
    return thing1.place === thing2.place
        && thing1.name === thing2.name;
}

removeDuplicates(things.thing, thingsEqual);

另一种方法是使用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()。

 var testArray= ['a','b','c','d','e','b','c','d'];

 function removeDuplicatesFromArray(arr){

 var obj={};
 var uniqueArr=[];
 for(var i=0;i<arr.length;i++){ 
    if(!obj.hasOwnProperty(arr[i])){
        obj[arr[i]] = arr[i];
        uniqueArr.push(arr[i]);
    }
 }

return uniqueArr;

}
var newArr = removeDuplicatesFromArray(testArray);
console.log(newArr);

Output:- [ 'a', 'b', 'c', 'd', 'e' ]

另一个选项是创建一个自定义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;
    },[]);

考虑lodash.uniqWith

const objects = [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }, { 'x': 1, 'y': 2 }];
 
_.uniqWith(objects, _.isEqual);
// => [{ 'x': 1, 'y': 2 }, { 'x': 2, 'y': 1 }]