Javascript ES6集合(SET)类型✪ ω ✪

Posted XianZhe_

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript ES6集合(SET)类型✪ ω ✪相关的知识,希望对你有一定的参考价值。

javascript ES6集合(SET)类型✪ ω ✪

文章目录


一、集合

集合(Set),是ES6中新出的数据类型,这于数学中的集合概念是一样的。
在讲解 JS 的集合之前,我觉得还是有必要先回顾一下数学集合中的主要分类:并集,交集,差集

JavaScript 集合特性

  • Set是ES6提供的新的数据结构,允许存储任何数据类型。
  • 天生去重性,每个元素都是唯一,互不相同,这是也是集合最主要的特点。
  • 可以根据插入的顺序迭代它的元素。

简单概况: 集合是一个无序且不重复的数据类型


二、利用其去重性👲🏻

上面已经提到过了,集合天生去重,那么可以利用集合的去重性去做一些事情

  • 数组去重:
    张三使用了障眼法,造出了多个假的张三,看看罗老师如何去治张三

    // const name = ['张三', '张三', '张三', '张三', '张三', '张三', '张三', '张三', '张三', '张三', '罗翔']
    let names = Array(10).fill("张三", 0, 10)             // 也可以这样去添加多个张三
    names.push("罗翔");
    names = [...new Set(names)]
    console.log(names)
    
    ["张三", "罗翔"]
    

    是吧,使用集合一下就能破解张三的障眼法,揪出唯一的一个张三

  • 接下来看一个去重性的应用,不重复抽奖

    const res = new Set();
    const names = ["张三", "李四", "小明", "李华", "约翰", "Jone", "Mark", "Bill", "PrettyGirl"];
    while (res.size < 3) 
        res.add(names[Math.abs(parseInt(Math.random() * 8))])
    
    console.log(res)
    

    程序逻辑: 使用到了random 随机选出一个名字,在将此名字添加到集合里,如果是重复的将不进行添加操作,循环条件为判断集合人数是否小于3


三、迭代Set

在讲解下面的内容前,有必要去了解一下集合中的数据结构。

  • 要先明白的是传统的索引方法是无法取出集合数据。

     const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
     for (let i=0; i < vegetable.size; i++) 
         // 无法取出, 输出结果为undefined
         console.log(vegetable[i])
     
    
  • 因为集合没有索引的原因,使用for in 循环也是无法取值。

    const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
    // 循环不执行
    for (let key in vegetable) 
        console.log(key)
    
    
  • 只有使用 for of 循环方式进行取值,才能有结果

    const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
    for (let value of vegetable) 
        console.log(value)
    
    
    青菜
    萝卜
    苹果
    香蕉
    土豆
    橘子
    

四、集合实例对象的方法

1)、Set.prototype.add(value)

在Set对象尾部添加一个元素,并且返回该Set对象。

const vegetable = new Set(["青菜", "萝卜"]);
vegetable.add("苹果");
console.log(vegetable);

根据会返回该Set对象的原理,可以实现对于该Set对象的链式操作。

const vegetable = new Set(["青菜", "萝卜"]);
vegetable.add("苹果").add("香蕉").add("土豆").add("橘子");
console.log(vegetable);
"青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"

2)、Set.prototype.clear()

移除Set对象内的所有元素。

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
vegetable.clear();
console.log(vegetable);     // 清空后集合为空

3)、Set.prototype.delete(value)

移除集合中与这个值相等的元素,并返回是否删除成功。
在执行删除操作前,程序内部会先执行Set.prototype.has(value),判断要删除的元素是否存在, 如果该元素存在,则在删除元素后返回 true,否则返回 false

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
const r1 = vegetable.delete("萝卜");
const r2 = vegetable.delete("卜萝");
console.log(r1, r2);
true false

4)、Set.prototype.entries()

返回一个新的迭代器对象,该对象包含集合对象中的按插入顺序排列的所有元素的值的[value, value] 数组,因为集合只有值的存在,所以数组中的元素都是相等的。

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
for (let [key, value] of vegetable.entries()) 
    console.log(key, value);

5)、Set.prototype.forEach(callbackFn[, thisArg])

按照插入顺序,为Set对象中的每一个值调用一次callBackFn。如果提供了thisArg参数,回调中的this会是这个参数。

参数如下:

  • callbackFn: 为集合中每个元素执行的回调函数,该函数接收三个参数:
    • currentValue: 正在被操作的元素。
    • currentKey:由于集合没有索引,所以 currentKey 也表示这个正在被操作的元素。
    • set:调用当前 forEach 方法的集合对象。
  • thisArg:回调函数执行过程中的 this 值。

演示代码: 👇

vegetable.forEach(function (currentValue, currentKey, set) 
    console.log(currentValue, currentKey, set)
)
青菜 青菜 Set(6)'青菜', '萝卜', '苹果', '香蕉', '土豆',…
萝卜 萝卜 Set(6)'青菜', '萝卜', '苹果', '香蕉', '土豆',…
......

6)、Set.prototype.has(value)

返回一个布尔值,表示该值在Set中存在与否。

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
console.log(vegetable.has("土豆"));       // true
console.log(vegetable.has("豆土"));       // false

7)、Set.prototype.keys()

因为集合只有值的存在,与values()方法相同,返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
for (let item of vegetable.keys()) 
    console.log(item)

青菜
萝卜
苹果
香蕉
土豆
橘子

8)、Set.prototype.values()

返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。

const vegetable = new Set(["青菜", "萝卜", "苹果", "香蕉", "土豆", "橘子"]);
for (let item of vegetable.values()) 
    console.log(item)

青菜
萝卜
苹果
香蕉
土豆
橘子

9)、Set.prototype[@@iterator]()

返回一个新的迭代器对象,该对象包含Set对象中的按插入顺序排列的所有元素的值。用法与 Set.prototype.keys()Set.prototype.values() 方法一样。

for (let item of vegetable[Symbol.iterator]()) 
    console.log(item)

青菜
萝卜
苹果
香蕉
土豆
橘子

实际上,Set.prototype.keys()Set.prototype.values() 方法返回也是一个迭代器对象,数据内容一致。使用 next() 方法进行观察。

const iterator = vegetable[Symbol.iterator]()
console.log("iterator:", iterator.next())
console.log("iterator:", iterator.next())

const keys = vegetable.keys()
console.log("keys:", keys.next())
console.log("keys:", keys.next())

const values = vegetable.values()
console.log("values:", values.next())
console.log("values:", values.next())

五、扩展集合方法

1)、向集合原型添加方法

/**
 * 更新(update)集合,添加来自 others 中的所有元素, 灵感来自Python
 * @param others: 可迭代对象
 * @return Set<any> 添加结果后集合
 */
Set.prototype.update = function (others) 
    if (others.constructor === Set) 
        for (let i of others) 
            this.add(i);
        
     else 
        for (let i = 0; i < others.length; i++) 
            this.add(others[i]);
        
    
    return this


/**
 * 更新集合,移除也存在于 others 中的元素,也就是移除两个集合中都存在的元素
 * @param elems 需要更新的另一集合
 * @return Set<any> 返回新的集合
 */
Set.prototype.difference_update = function (elems) 
    for (let e of elems) 
        if (this.has(e)) 
            this.delete(e);
         else 
            this.add(e);
        
    
    return this


/**
 * 返回集合的差集方法, 灵感来自Python
 * @param set 需要比较的另一集合
 * @returns Set<any> 差集集合
 */
Set.prototype.difference = function (set) 
    const diff = new Set();
    for (let item of set) 
        if (!this.has(item)) 
            diff.add(item);
        
    
    return diff


/**
 * 返回集合的交集方法, 灵感来自Python
 * @param set 需要比较的另一集合
 * @returns Set<any> 交集集合
 */
Set.prototype.intersection = function (set) 
    const common = new Set();
    for (let item of set) 
        if (this.has(item)) 
            common.add(item);
        
    
    return common


/**
 * 返回集合的并集方法, 灵感来自Python
 * @param set 需要合并的另一集合
 * @returns Set<any> 合并集合
 */
Set.prototype.union = function (set) 
    return this.update(set)


/**
 * 获取集合长度
 * @return number 长度值
 */
Set.prototype.length = function () 
    return this.size;

2)、继承
如果想在不影响原本集合构造函数的前提下扩展集合的方法,可以使用继承集合的方式对其扩展。

class MySet extends Set 
    /**
     * 更新(update)集合,添加来自 others 中的所有元素, 灵感来自Python
     * @param others: 可迭代对象
     * @return Set<any> 添加结果后集合
     */
    update(others) 
        if (others.constructor === Set) 
            for (let i of others) 
                this.add(i);
            
         else 
            for (let i = 0; i < others.length; i++) 
                this.add(others[i]);
            
        
        return this
    

    /**
     * 更新集合,移除也存在于 others 中的元素,也就是移除两个集合中都存在的元素
     * @param elems 需要更新的另一集合
     * @return Set<any> 返回新的集合
     */
    difference_update(elems) 
        for (let e of elems) 
            if (this.has(e)) 
                this.delete(e);
             else 
                this.add(e);
            
        
        return this
    

    /**
     * 返回集合的差集方法, 灵感来自Python
     * @param set 需要比较的另一集合
     * @returns Set<any> 差集集合
     */
    difference(set) 
        const diff = new Set();
        for (let item of set) 
            if (!this.has(item)) 
                diff.add(item);
            
        
        return diff
    

    /**
     * 返回集合的交集方法, 灵感来自Python
     * @param set 需要比较的另一集合
     * @returns Set<any> 交集集合
     */
    intersection(set) 
        const common = new Set();
        for (let item of set) 
            if (this.has(item)) 
                common.add(item);
            
        
        return common
    

    /**
     * 返回集合的并集方法, 灵感来自Python
     * @param set 需要合并的另一集合
     * @returns Set<any> 合并集合
     */
    union(set) 
        return this.update(set)
    

    length() 
        return this.size;
    


参考资料💖

官方文档:


相关博客👒

以上是关于Javascript ES6集合(SET)类型✪ ω ✪的主要内容,如果未能解决你的问题,请参考以下文章

ES6之Set集合数据类型

ES6 从入门到精通 # 10:Set 集合数据类型

ES6 从入门到精通 # 10:Set 集合数据类型

ES6 Map与Set

ES6 中的 SetMap 和 WeakMap

理解数据结构之Set,只要5分钟!