自 ES6 以来,获取没有重复项目的数组的代码变得优雅:
[...new Set(array)];
就是这样!
但是,如果数组包含具有基本数据类型(字符串,布尔值,数字......)的元素,则仅删除重复项。
一组对象文字怎么样?如何在不重复的情况下完成这项工作,使用接近上面使用的语法的语法?
var array=["aaa","bbb","aaa","cc","aaa","bbb"];
var out=[...new Set(array)];
console.log(out)
//----Literal Object
array=[{n:"J",last:"B"},{n:"J",last:"B"}];
out=[...new Set(array)];
console.log(out)
上面的代码生成一个包含2个元素的集合,但我希望在这种情况下只有一个元素。
我可以使用序列化/反序列化方法来实现这一目标:
[...new Set(array.map(
//-- SERIALIZE:
(e) => `${e.n}:${e.last}`
))].map(
//-- DE-SERIALIZE:
(e) => ({ n: `${e.split(':')[0]}`, last: `${e.split(':')[1]}` })
)
但是,我正在寻找内置的ES6。
答案 0 :(得分:1)
在JavaScript中,如果它们不是相同的引用,则两个对象是不同的,即使它们看起来相同:
var a = {};
var b = {};
console.log(a === b); // false
b = a;
console.log(a === b); // true
设置类似的工作:除非添加到它的对象引用相同的东西,否则它们将是不同的。
让它按照您的意愿工作的一个想法是创建自己的Set风格,即 MySet ,为它提供它作为Set工作所需的所有方法和属性。 / p>
然后在其实现中,您将在其内部保留一个Map,您可以在其中为您存储的所有内容提供密钥。然后,您可以确保您认为相同的对象在该映射中获得相同的密钥,因此只存储一次。
使用JSON.stringify(item)
作为关键是一种非效率但直截了当的方法。这有其局限性(例如,添加自引用对象会使JSON.stringify(item)
放弃),但其余的则可以完成工作。
我们可以使 MySet 接受另一个参数:调用以获取项目键值的函数。鉴于上述想法,我们会给它默认值JSON.stringify
。
考虑这个实现,添加测试代码:
// Implementation of special Set:
class MySet {
constructor(values = [], keyFunc = JSON.stringify) {
// Use a map to store the values
this._map = new Map();
// Which function to use for generating an item's key
this._keyFunc = keyFunc;
// Add the initial values
for (var value of [...values]) this.add(value);
}
get size() {
return this._map.size;
}
add(item) {
// Key items by the given function
this._map.set(this._keyFunc(item), item);
}
has(item) {
return this._map.has(this._keyFunc(item));
}
*[Symbol.iterator] () {
for (var pair of this._map) {
yield pair[1]; // return the item
}
}
// etc...
}
// Test it:
array = [{n:"J",last:"B"}, {n:"J",last:"B"}];
out = [...new MySet(array)];
console.log(out);

正如您所看到的,虽然在集合中添加了两个对象,但它只存储了一个。