使用Set

时间:2016-07-25 20:21:48

标签: arrays functional-programming ecmascript-6 unique

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。

1 个答案:

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




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