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

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

当前回答

我们可以利用Javascript的Set对象和Array的Filter函数:例如:

//示例阵列const arr=[{id:“1”},{id:“2”};//收集要过滤元素的唯一元素Id。constuniqIds=arr.reduce((id,el)=>ids.add(el.id),new Set());//过滤出uniq元素。const uniqElements=arr.filter((el)=>uniqIds.delete(el.id));console.log(uniqElements);

其他回答

让myData=[{place:“here”,name:“stuff”},{地点:“there”,名称:“morestuff”},{地点:“there”,名称:“morestuff”}];let q=[…new Map(myData.Map(obj=>[JSON.stringify(obj),obj]).values()];控制台日志(q)

一个使用ES6和new Map()的命令行。

// assign things.thing to myData
let myData = things.thing;

[...new Map(myData.map(obj => [JSON.stringify(obj), obj])).values()];

详细信息:-

对数据列表执行.map()并将每个单独的对象转换为[key,value]对数组(长度=2),第一个元素(key)将是对象的字符串化版本,第二个元素(value)将是一个对象本身。将上述创建的数组列表添加到新的Map()中会将键作为字符串化对象,任何相同的键添加都会导致覆盖现有的键。使用.values()将为MapIterator提供Map中的所有值(在本例中为obj)最后,传播。。。运算符为新数组提供上述步骤中的值。

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实例。

你听说过洛达什图书馆吗?当您不想将逻辑应用于代码时,我建议您使用此实用程序,并使用已优化且可靠的现有代码。

考虑制作一个这样的数组

things.thing.push({place:"utopia",name:"unicorn"});
things.thing.push({place:"jade_palace",name:"po"});
things.thing.push({place:"jade_palace",name:"tigress"});
things.thing.push({place:"utopia",name:"flying_reindeer"});
things.thing.push({place:"panda_village",name:"po"});

注意,如果您想保持一个属性的唯一性,您可以使用lodash库来实现这一点。在这里,您可以使用_.uniqBy

.uniqBy(数组,[iteratee=.identity])

此方法类似于_.uniq(它返回一个数组的无重复版本,其中只保留每个元素的第一次出现),只是它接受iterate,iterate为数组中的每个元素调用,以生成计算唯一性的标准。

因此,例如,如果要返回具有唯一属性“place”的数组

_.uniqBy(things.thing,'place')

同样,如果您希望唯一属性为“name”

_.uniqBy(things.thing,'name')

希望这有帮助。

干杯

如果您可以等到所有添加之后再消除重复项,典型的方法是首先对数组进行排序,然后消除重复项。排序避免了在遍历每个元素时扫描数组的N*N方法。

“消除重复项”函数通常称为unique或uniq。一些现有的实现可以结合这两个步骤,例如原型的uniq

如果你的图书馆还没有,这篇文章没有什么想法可以尝试(还有一些需要避免:-)!我个人认为这是最直接的:

    function unique(a){
        a.sort();
        for(var i = 1; i < a.length; ){
            if(a[i-1] == a[i]){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }  

    // Provide your own comparison
    function unique(a, compareFunc){
        a.sort( compareFunc );
        for(var i = 1; i < a.length; ){
            if( compareFunc(a[i-1], a[i]) === 0){
                a.splice(i, 1);
            } else {
                i++;
            }
        }
        return a;
    }

这个呢

function dedupe(arr, compFn){
    let res = [];
    if (!compFn) compFn = (a, b) => { return a === b };
    arr.map(a => {if(!res.find(b => compFn(a, b))) res.push(a)});
    return res;
}