使用Set的ES6中没有重复的文字对象数组 [英] Array of literal Objects without duplicates in ES6 using Set

查看:509
本文介绍了使用Set的ES6中没有重复的文字对象数组的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

ES6

  [ ...新的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个元素的集合,但是我希望它只有一个在这个元素中case。



我可以使用序列化/反序列化方法来实现这一点:

  [... new set(array.map(
// - SERIALIZE:
(e)=>`$ {en}:$ {e.last}`
$(e)=>({n:`$ {e.split(':')[0]})。map(
// - DE-SERIALIZE:
,last:`$ {e.split(':')[1]}`})

然而,我正在寻找一个内置的ES6。

解决方案

在JavaSc如果它们不是相同的引用,即使它们看起来相同,ript两个对象也不相同:

  var a = {}; 
var b = {};
console.log(a === b); // false
b = a;
console.log(a === b); // true

设置工作类似:除非添加的对象指向相同的东西,否则不同的。

一个自定义集



使它像你想要的那样工作的一个想法是创建你的自己的Set,即 MySet 的风格,给它所需的所有方法和属性作为Set。



然后在其中你可以在内部保存一个Map,在那里你可以为你存储的所有东西提供一个键。然后,您可以确保您认为相同的对象,在该地图中获得相同的密钥,因此只能存储一次。



一个非效率但简单这样做的方法是使用 JSON.stringify(item)作为关键字。这有其局限性(例如添加自引用对象会使 JSON.stringify(item)放弃),但其余部分完成这项工作。



我们可以让接受一个额外的参数:调用获取项目的键值的函数。鉴于上述想法,我们会给它默认值 JSON.stringify



考虑这个实现,测试代码添加到它:



//实现特殊的Set:class MySet {构造函数(值= [],keyFunc = JSON.stringify){//使用地图来存储值this._map = new Map(); //使用哪个函数来生成项目的密钥this._keyFunc = keyFunc; //为(var value of [... values])添加初始值this.add(value); } get size(){return this._map.size; } add(item){//通过给定函数的关键项目this._map.set(this._keyFunc(item),item); } has(item){return this._map.has(this._keyFunc(item)); } * [Symbol.iterator](){for(var this this._map){yield pair [1]; //测试它:array = [{n:J,last:B},{n:J,last:B}] ; out = [... new MySet(array)]; console.log(out);

正如你所看到的,尽管有两个对象被添加到集合中,但它只存储了一个。


The code to get an array without repeated items has become elegant since ES6:

[...new Set(array)];

That's it!

However, this is only removing duplicates if the array has elements with a primitive data type (string, boolean, number, ...).

What about a Set of object literals? How to make that work without getting duplicates, using a syntax close to the syntax used above?

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)

The code above produces a set with 2 elements, yet I want it to only have one in this case.

I could use serialize/de-serialize methodology to achieve this:

[...new Set(array.map(
    //-- SERIALIZE:
    (e) => `${e.n}:${e.last}`
))].map(
    //-- DE-SERIALIZE:
    (e) => ({ n: `${e.split(':')[0]}`, last: `${e.split(':')[1]}` })
)

However, I am looking for an ES6 built-in.

解决方案

In JavaScript two objects are different if they are not the same reference, even when they look the same:

var a = {};
var b = {};
console.log(a === b); // false
b = a;
console.log(a === b); // true

Sets work similarly: unless objects added to it are referring to the same thing, they will be distinct.

A Custom Set

One idea to make it work like you want, is to create your own flavour of Set, i.e. MySet, giving it all the methods and properties you need for it to work as a Set.

Then in its implementation you would keep a Map in its internals, where you give a key to everything you store in it. You could then make sure that objects that you consider the same, get the same key in that map, and so are only stored once.

A non-efficient, but straightforward way of doing that, is to use JSON.stringify(item) as key. This has its limitations (e.g. adding self-referencing objects will make JSON.stringify(item) give up), but for the rest it does the job.

We could make MySet to accept an additional argument: the function to invoke to get an item's key value. Given the above idea, we would give it the default value JSON.stringify.

Consider this implementation, with your testing code added to it:

// 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);

As you can see, although two objects were added to the set, it has only stored one.

这篇关于使用Set的ES6中没有重复的文字对象数组的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆