Iwen's blog Iwen's blog
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于

Iwen

不摸鱼的哥哥
首页
  • 前端文章

    • JavaScript
    • Vue
  • 学习笔记

    • 《JavaScript教程》笔记
    • 《JavaScript高级程序设计》笔记
    • 《ES6 教程》笔记
    • 《Vue》笔记
    • 《TypeScript 从零实现 axios》
    • 小程序笔记
  • HTML
  • CSS
  • 技术文档
  • GitHub技巧
  • Nodejs
  • 博客搭建
  • Linux
  • 学习
  • 面试
  • 心情杂货
  • 友情链接
  • 网站
  • 资源
  • Vue资源
  • 分类
  • 标签
  • 归档
复盘
关于
  • Vue

  • Vue进阶

  • CSS

  • ES6

  • Base

  • Core

  • Array

  • Object

  • String

  • Async

  • Browser

  • Http

  • 性能优化

  • 正则

  • 经典总结

  • 设计模式

  • 数据结构

    • 栈
    • 队列
    • 链表
    • 树
    • 集合
      • 实现
      • 并集
      • 交集
      • 差集
      • 子集
    • 字典
    • 图
    • 散列表
    • 堆
  • 算法

  • 手写

  • TypeScript

  • 复盘
  • 数据结构
Mr.w
2020-11-29

集合

# 集合(Set)

集合是一种无重复元素, 无顺序的数据结构。

ES6 引入的 Set 就是集合。

方法 描述
add 添加新元素
delete 移除元素
has 元素是否存在(Boolean)
clear 清除集合
size 集合数量
values 集合所有元素(Array)

# 实现

class Set {
    constructor() {
        this.items = {}
    }

    add(value) {
        if (!this.has(value)) {
            this.items[value] = value
            return true
        }
        return false
    }

    has(value) {
        return Object.prototype.hasOwnProperty.call(this.items, value)
    }

    delete(value) {
        if (this.has(value)) {
            delete this.items[value]
            return true
        }
        return false
    }

    clear() {
        this.items = {}
    }

    size() {
        let count = 0;
        for (let key in this.items) {
            if (this.items.hasOwnProperty) {
                count++
            }
        }
        return count
    }

    values() {
        let arr = []
        for (let key in this.items) {
            if (this.items.hasOwnProperty) {
                arr.push(key)
            }
        }
        return arr
    }

    data() {
        return this.items
    } 
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53

# 并集

对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。

union(otherSet) {
    const unionSet = new Set()

    let values = this.values()
    for (let i = 0; i < values.length; i++) {
        unionSet.add(values[i])
    }
    values = otherSet.values()
    for (let i = 0; i < values.length; i++) {
        unionSet.add(values[i])
    }

    return unionSet;
}

const setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)

const setB = new Set()
setB.add(3)
setB.add(4)
setB.add(5)

const union = setA.union(setB)
console.log(union.values())
// [1, 2, 3, 4, 5]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

注意元素3同时存在于setA和setB中,它在结果集合中只出现一次。

# 交集

对于给定的两个集合,返回一个包含两个集合中共有元素的新集合。

intersection(otherSet) {
    const intersectionSet = new Set()

    const values = this.values()
    for (let i = 0; i < values.length; i++) {
        if (otherSet.has(values[i])) {
            intersectionSet.add(values[i])
        }
    }
    return intersectionSet
}

const setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)

const setB = new Set()
setB.add(3)
setB.add(4)
setB.add(5)

const intersection = setA.intersection(setB)
console.log(intersection.values())
// [3]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

改进交集方法

假设我们有下面两个集合:

  • setA的值为[1, 2, 3, 4, 5, 6, 7]
  • setB的值为[4, 6]

使用我们创建的intersection方法,需要迭代七次setA的值,也就是setA中元素的个数,然后还要将这七个值和setB中的两个值进行比较。

如果我们只需要迭代两次setB就好了,更少的迭代次数意味着更少的过程消耗。那么就来优化代码,使得迭代元素的次数更少吧

intersection(otherSet) {
    const intersectionSet = new Set()

    const values = this.values()
    const otherValues = otherSet.values()

    let biggerSet = values;
    let smallerSet = otherValues;

    if (otherValues.length > values.length) {
        biggerSet = otherValues
        smallerSet = values
    }

    smallerSet.forEach(val => {
        if (biggerSet.includes(val)) {
            intersectionSet.add(val)
        }
    })
    
    return intersectionSet
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

# 差集

对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。

difference(otherSer) {
    const differenceSet = new Set()
    const values = this.values()

    values.forEach(val => {
        if (!otherSer.has(val)) {
            differenceSet.add(val)
        }
    })
    return differenceSet
}

const setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)

const setB = new Set()
setB.add(3)
setB.add(4)
setB.add(5)

const difference = setA.difference(setB)
console.log(difference.values())
// [1, 2]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 子集

验证一个给定集合是否是另一集合的子集。

isSubsetOf(otherSet) {
    let isSubset = true

    this.values().forEach(val => {
        if (!otherSet.has(val)) {
            isSubset = false
            return false
        }
        return true
    })

    return isSubset
}

const setA = new Set()
setA.add(1)
setA.add(2)
setA.add(3)

const setB = new Set()
setB.add(1)
setB.add(2)
setB.add(3)

const setC = new Set()
setC.add(3)
setC.add(4)
setC.add(5)

console.log(setA.isSubsetOf(setB))
console.log(setA.isSubsetOf(setC))
// true false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

我们有三个集合:setA是setB的子集(因此输出为true),然而setA不是setC的子集(setC只包含了setA中的2,而不包含1),因此输出为false。

树
字典

← 树 字典→

最近更新
01
flex布局页面自适应滚动条问题
12-28
02
前后端分离开发请求接口跨域如何携带cookie的问题
12-28
03
怎么实现div长宽比固定width-height4比3
12-28
更多文章>
Theme by Vdoing | Copyright © 2017-2022 Iwen | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式