JS - 在Array中使用带对象的Set()

时间:2018-04-13 15:16:16

标签: javascript arrays ecmascript-6

如何在对象中使用Set()?我阅读了文档,它使用数组中的值,但对象不起作用。为什么?我想避免重复项具有相同的值。

let nameList_one = [{ name: 'harry', id: 1 }, { name: 'john', id: 2 }, { 'name': 'trevor', id: 3  }]
let nameList_two = [{ name: 'harry', id: 1  }, { name: 'ron', id: 4  }, { name: 'jackson', id: 5  }]

let fullNameList = [...nameList_one , ...nameList_two ]

let filteredList = [...new Set(fullNameList)] // the output is the merge of two array, duplicating "harry".

输出:

  

[{name:'harry',id:1},{name:'john',id:2},{'name':'trevor',id:3},{name:'harry',id :1},{name:'ron',id:4},{name:'jackson',id:5}]

预期输出:

  

[{name:'harry',id:1},{name:'john',id:2},{'name':'trevor',id:3},{name:'ron',id :4},{name:'jackson',id:5}]

谢谢!

3 个答案:

答案 0 :(得分:1)

这样做的好方法是继承Set

class UniqueNameSet extends Set {
    constructor(values) {
        super(values);

        const names = [];
        for (let value of this) {
            if (names.includes(value.name)) {
                this.delete(value);
            } else {
                names.push(value.name);
            }
        }
    }
}

这为您提供了Set的所有其他方法/属性,但添加了您正在寻找的额外功能。

答案 1 :(得分:1)

每个对象都是一个指向内存地址的指针,因此即使两个对象具有相同的属性,它也不会相等。 一种方法是使用JSON.stringify并复制字符串化对象。

答案 2 :(得分:1)

这不适用于对象,因为它们不是同一个对象:

{ name: 'harry', id: 1 } !== { name: 'harry', id: 1 }

可行的方法是:

let filteredList = [...new Set(fullNameList.map(JSON.stringify))].map(JSON.parse);

不建议这样做,因为它在不必要的地方使用序列化。序列化将销毁无法序列化的对象实例,将忽略不可枚举的属性,并且不会处理循环引用。具有不同属性顺序的对象不会作为重复项删除;他们的属性应该先排序,这使得这种方法不切实际。

如果对象由一个或多个字段标识,则可以使用带有序列化字段作为地图键的Map

let filteredList = [
  ...new Map(fullNameList.map(obj => [`${obj.id}:${obj.name}`, obj]))
  .values()
];