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

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

当前回答

removeDucplicates()接受一个对象数组,并返回一个没有任何重复对象的新数组(基于id属性)。

const allTests = [
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'},
  {name: 'Test2', id: '2'},
  {name: 'Test3', id: '3'}
];

function removeDuplicates(array) {
  let uniq = {};
  return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true))
}

removeDuplicates(allTests);

预期结果:

[
  {name: 'Test1', id: '1'}, 
  {name: 'Test3', id: '3'},
  {name: 'Test2', id: '2'}
];

首先,我们将变量uniq的值设置为空对象。

接下来,我们过滤对象数组。Filter创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

return array.filter(obj => !uniq[obj.id] && (uniq[obj.id] = true));

上面,我们使用了&&的短路功能。如果&&的左侧求值为true,则返回&&右侧的值。如果左侧为false,则返回&&左侧的内容。

对于每个对象(obj),我们检查uniq中名为obj.id值的属性(在这种情况下,在第一次迭代时,它将检查属性“1”。)我们希望它返回的结果(true或false)相反,这就是为什么我们使用!在里面uniq[obj.id]。如果uniq已经具有id属性,则返回true,其计算结果为false(!),告诉过滤函数不要添加该obj。但是,如果未找到obj.id属性,它返回false,然后计算结果为true(!)并返回&&或(uniq[obj.id]=true)右侧的所有内容。这是一个truthy值,告诉filter方法将该obj添加到返回的数组中,并且还将属性{1:true}添加到uniq中。这确保不会再添加具有相同id的任何其他obj实例。

其他回答

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

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

这是我的两分钱。如果您知道财产的顺序相同,则可以将元素串接起来,并从数组中删除重复项,然后再次解析数组。类似于:

var things=新对象();things.thing=新数组();thing.thing.push({place:“here”,name:“stuff”});things.thing.push({place:“there”,name:“morestuff”});things.thing.push({place:“there”,name:“morestuff”});let-stringified=things.thing.map(i=>JSON.sringify(i));let unique=stringified.filter((k,idx)=>stringified.indexOf(k)==idx).map(j=>JSON.parse(j))console.log(唯一);

我有一个完全相同的要求,即基于单个字段上的重复项删除数组中的重复对象。我在这里找到了代码:Javascript:从对象数组中删除重复项

所以在我的示例中,我要从数组中删除具有重复licenseNum字符串值的任何对象。

var arrayWithDuplicates = [
    {"type":"LICENSE", "licenseNum": "12345", state:"NV"},
    {"type":"LICENSE", "licenseNum": "A7846", state:"CA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"OR"},
    {"type":"LICENSE", "licenseNum": "10849", state:"CA"},
    {"type":"LICENSE", "licenseNum": "B7037", state:"WA"},
    {"type":"LICENSE", "licenseNum": "12345", state:"NM"}
];

function removeDuplicates(originalArray, prop) {
     var newArray = [];
     var lookupObject  = {};

     for(var i in originalArray) {
        lookupObject[originalArray[i][prop]] = originalArray[i];
     }

     for(i in lookupObject) {
         newArray.push(lookupObject[i]);
     }
      return newArray;
 }

var uniqueArray = removeDuplicates(arrayWithDuplicates, "licenseNum");
console.log("uniqueArray is: " + JSON.stringify(uniqueArray));

结果:

uniqueArray是:

[{"type":"LICENSE","licenseNum":"10849","state":"CA"},
{"type":"LICENSE","licenseNum":"12345","state":"NM"},
{"type":"LICENSE","licenseNum":"A7846","state":"CA"},
{"type":"LICENSE","licenseNum":"B7037","state":"WA"}]

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

这个解决方案最适合我,因为它使用了Array.from方法,而且它的长度更短,可读性更强。

let person = [
{name: "john"}, 
{name: "jane"}, 
{name: "imelda"}, 
{name: "john"},
{name: "jane"}
];

const data = Array.from(new Set(person.map(JSON.stringify))).map(JSON.parse);
console.log(data);