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

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

当前回答

您还可以创建一个通用函数,该函数将根据传递给该函数的对象键过滤数组

function getUnique(arr, comp) {

  return arr
   .map(e => e[comp])
   .map((e, i, final) => final.indexOf(e) === i && i)  // store the keys of the unique objects
   .filter(e => arr[e]).map(e => arr[e]); // eliminate the dead keys & store unique objects

 }

你可以这样调用函数,

getUnique(things.thing,'name') // to filter on basis of name

getUnique(things.thing,'place') // to filter on basis of place

其他回答

在一行中使用ES6+,您可以按键获得唯一的对象列表:

const key = 'place';
const unique = [...new Map(arr.map(item => [item[key], item])).values()]

可以将其放入函数中:

function getUniqueListBy(arr, key) {
    return [...new Map(arr.map(item => [item[key], item])).values()]
}

下面是一个工作示例:

常量arr=[{地点:“这里”,名称:“x”,其他:“其他stuff1”},{地点:“那里”,名称:“x”,其他:“其他stuff2”},{地点:“这里”,名称:“y”,其他:“其他stuff4”},{地点:“这里”,名称:“z”,其他:“其他stuff5”}]函数getUniqueListBy(arr,key){return[…new Map(arr.Map(item=>[item[key],item])).values()]}const arr1=getUniqueListBy(arr,'place')console.log(“按位置唯一”)console.log(JSON.stringify(arr1))console.log(“\n名称唯一”)const arr2=getUniqueListBy(arr,'name')console.log(JSON.stringify(arr2))

它是如何工作的

首先,以可以用作Map输入的方式重新映射数组。

arr.map(项=>[项[键],项]);

这意味着阵列的每个项目将被转换为具有2个元素的另一个阵列;选定的键作为第一个元素,整个初始项作为第二个元素,这称为条目(例如数组条目、映射条目)。这是一个官方文档,其中有一个示例显示了如何在Map构造函数中添加数组项。

放置钥匙时的示例:

[["here", {place: "here",  name: "x", other: "other stuff1" }], ...]

其次,我们将这个修改后的数组传递给Map构造函数,这就是神奇的发生。映射将消除重复的关键字值,只保留同一关键字的最后插入值。注意:贴图保持插入顺序。(检查贴图和对象之间的差异)

新映射(上面刚刚映射的条目数组)

第三,我们使用map值来检索原始项,但这次没有重复项。

新映射(mappedArr).values()

最后一个是将这些值添加到一个新的数组中,这样它可以看起来像初始结构,并返回:

return[…new Map(mappedArr).values()]

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

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

使用Set的一个衬垫

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”});//为简洁起见,将things.thing分配给myDatavar myData=things.thing;things.thing=数组.from(新集合(myData.map(JSON.stringify))).map(JSON解析);console.log(things.thing)

说明:

newSet(myData.map(JSON.stringify))使用字符串化的myData元素创建一个Set对象。Set对象将确保每个元素都是唯一的。然后,我使用array.from基于创建的集合的元素创建一个数组。最后,我使用JSON.parse将字符串化元素转换回对象。

如果您可以使用诸如下划线或lodash之类的Javascript库,我建议查看它们库中的_.uniq函数。来自lodash:

_.uniq(array, [isSorted=false], [callback=_.identity], [thisArg])

基本上,您传入数组,这里是一个对象文本,然后传入要在原始数据数组中删除重复项的属性,如下所示:

var data = [{'name': 'Amir', 'surname': 'Rahnama'}, {'name': 'Amir', 'surname': 'Stevens'}];
var non_duplidated_data = _.uniq(data, 'name'); 

更新:Lodash现在也引入了.uniqBy。

基本方法是:

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