对象数组如何去重?

const testA = [
    {
        name: "10EK"
    },
    {
        name: "10BC"
    },
    {
        name: "10BC"
    },
    {
        name: "10EK"
    },
    {
        name:"10EK"
    },
    {
        name:"10GB"
    },
    {
        name: "10GB"
    }
];
阅读 4.8k
6 个回答
const r = [...new Map(testA.map(item => [item.name, item])).values()];
console.log(r);

@戡玉 的方法相比,这个方法可以保留原对象(如果对象不只 name 属性呢)。

但是在以 name 作为唯一值判断的情况下,其他属性可能会存在不同,那到底留哪一个对象就会有讲究。按上面的算法,留下来的是最后出现的那个。

如果想留最早出现的那个,可以先把数组 reverse() 再按上面的方法进行处理。但要注意的是 reverse() 会改变原数组。如果不想改变原数组可以这样:

[...new Map([...testA].reverse().map(item => [item.name, item])).values()]

或者直接使用遍历的办法(还是需要 Set 或对象来辅助判重)

function distinct(arr) {
    const names = new Set();
    const result = [];
    arr.forEach(it => {
        if (names.has(it.name)) {
            return;
        }
        names.add(it.name);
        result.push(it);
    });
    return result;
}

这样做(留先出现的)甚至可以保持原来的顺序。

如果想留最后出现的那个,同样可以先 reverse() 再来 forEach()。如果需要保持原来的顺序,再把结果 reverse() 一次。另一种方法是:直接用索引号,从后往前遍历,遇到需要加入 result 的使用 unshift 代替 push 来加入。

总之……方法很多!

可以使用lodash的uniqBy
写法也比较简洁
_.uniqBy(testA, 'name');

Lodash 是一个一致性、模块化、高性能的 JavaScript 实用工具库。
如果对实现感兴趣也可以去看看具体的内部实现

下面的方法都是大同小异

Object.values(testA.reduce((acc,cur)=>Object.assign(acc,{[cur.name]:cur}),{}));
Object.values(Object.fromEntries(testA.map(item=>[item.name,item])))
var m= new Map();
testA.forEach(item=>{
        m.set(item.name,item);
   })
Array.from(m.values())
var s = new Set();
testA.filter(item=>{
    if(!s.has(item.name)){
        s.add(item.name);
        return true;
    } 
   })
var a=[];
var res =[];
for(index in testA){
   if(!a.includes(testA[index].name)){
     a.push(testA[index].name);
     res.push(testA[index]);
  }
}
console.log(res);
function unique(arr) {
    var cache = {};
    var ret = arr.slice();
    loop: for (var i = 0; i < ret.length; ++i) {
        var item = ret[i];
        for (var key in item) {
            var value = item[key];
            if (!cache.hasOwnProperty(key)) {
                cache[key] = [value];
            } else if (~cache[key].indexOf(value)) {
                ret.splice(i--, 1);
                continue loop;
            } else {
                cache[key].push(value);
            }
        }
    }
    return ret;
}
console.dir(unique(testA));

[...new Set(testA.map(o=>o.name))].map(name=>({name}))

新手上路,请多包涵
testA.reduce((p,v)=>{ p.find(v1=> v1.name === v.name) ? null : p.push(v) ;return p;}, [])
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题