Set

Set 是一个集合类型,它跟数组很像,但里面的元素只能出现一次。

以下代码创建一个空集合,并往里面添加元素。

$$jsdemo$$
$$edit$$
let set = new Set() // 创建空集合

set.add(1) // 将元素添加到数组中
set.add(2)
set.add(2) // 只会存在一个数字

console.log(set) // Set(3) {1, 2}

属性和方法

Set 类型的属性和方法比较少,因此都列在了以下表格中。

属性 描述
size 返回集合的元素数量。
方法 描述
new Set([iterable]) 创建一个集合,可选地接收一个可迭代对象并转换为集合。
add(item) 添加一个元素并返回自身。
delete(item) 删除一个元素,如果元素存在返回 true 否则返回 false。
has(item) 判断元素是否存在于集合中。
clear() 清空集合。

集合转数组

使用 Array.from

$$jsdemo$$
$$edit$$
let students = new Set(["鸣人", "柯南", "路飞"])

let arr = Array.from(students)

alert(Array.isArray(arr)) // true
alert(arr) // 鸣人,柯南,路飞

使用展开语法

$$jsdemo$$
$$edit$$
let students = new Set(["鸣人", "柯南", "路飞"])

let arr = [...students]

alert(Array.isArray(arr)) // true
alert(arr) // 鸣人,柯南,路飞

集合和数组的区别

$$tip

这里仅仅介绍一些比较明显且重要的细节,一些细微的点可能不会提及。

$$

长度

集合的长度属性是 size ,而数组是 length

集合没有顺序

无法通过下标获取

集合中保存的元素不会按顺序排列,因此也无法通过下标获取其中的值。


$$jsdemo$$
$$edit$$
let set = new Set([1, 2, 3, 4, 5])

alert(set[0]) // undefined
alert(set[1]) // undefined

for … in 无效

自然也无法使用 for ... in 循环下标。

$$jsdemo$$
$$edit$$
let set = new Set([1, 2, 3, 4, 5])

for (let i in set) {
    alert(i) // 不会被执行
}

不过 for ... of 依旧能正常作用于集合。

$$jsdemo$$
$$edit$$
let set = new Set([1, 2, 3, 4, 5])

for (let item of set) {
    alert(item)
}

集合运算

集合运算是一个基本的数学操作,可惜的是,JavaScript 没有提供集合运算的方法,但我们可以自己实现。

$$tip

集合运算的实现并不唯一,你也可以根据自己的想法来实现。

$$

Untitled

交集

交集指的是多个集合中共同存在的部分。

比如要评三好学生,要颁奖给同时报了几个兴趣班的同学,适用交集运算。

$$jsdemo$$
$$edit$$
// 交集
function intersection(a, b) {
    let result = new Set()
    for (let x of b) {
        if (a.has(x)) {
            result.add(x)
        }
    }

    return result
}

let classA = new Set(["小樱", "鸣人", "路飞"])
let classB = new Set(["鸣人", "路飞", "柯南"])

let intersectionClass = intersection(classA, classB)
console.log(intersectionClass) // {'鸣人', '路飞'}

并集

并集指的是将多个集合合并成一个集合。

比如要统计几个兴趣班总的同学名单,就要过滤掉重复的同学,此时适用并集运算。

$$jsdemo$$
$$edit$$
// 并集
function union(a, b) {
    return new Set([...a, ...b])
}

let classA = new Set(["小樱", "鸣人", "路飞"])
let classB = new Set(["鸣人", "路飞", "柯南"])

let unionClass = union(classA, classB)
console.log(unionClass) // {'小樱', '鸣人', '路飞', '柯南'}

差集

假如存在集合 A、B,那么 A 对 B 进行差集运算就意味着在仅在 A 存在,不存在于 B 的部分。

$$tip

与并集交集运算顺序不影响结果不一样。差集会因运算顺序不同,结果也会不同。

$$

$$jsdemo$$
$$edit$$
// 差集
function difference(a, b) {
    let result = new Set(a)
    for (let x of b) {
        result.delete(x)
    }

    return result
}

let classA = new Set(["小樱", "鸣人", "路飞"])
let classB = new Set(["鸣人", "路飞", "柯南"])

let differenceClass = difference(classA, classB)
console.log(differenceClass) // {'小樱'}

对称差

对称差指的是多个集合中仅在一个集合中存在的部分。

$$jsdemo$$
$$edit$$
// 差集
function difference(a, b) {
    let result = new Set(a)
    for (let x of b) {
        result.delete(x)
    }

    return result
}

// 对称差
function symmetricDifference(a, b) {
    return new Set([...difference(a, b), ...difference(b, a)])
}

let classA = new Set(["小樱", "鸣人", "路飞"])
let classB = new Set(["鸣人", "路飞", "柯南"])

let sdClass = symmetricDifference(classA, classB)
console.log(sdClass) // {'小樱', '柯南'}

练习

  1. 以下定义了多个数组,将其放到一个集合中。
let nums1 = [2, 4, 6, 7]
let nums2 = [3, 4, 6, 1]
let nums3 = [1, 2, 5, 2]

$$answer

$$jsdemo$$
$$edit$$
let nums1 = [2, 4, 6, 7]
let nums2 = [3, 4, 6, 1]
let nums3 = [1, 2, 5, 2]

let numbers = new Set([...nums1, ...nums2, ...nums3])
console.log(numbers)

$$

  1. 存在三个班级的集合,需要给同时上三个班(交集)的同学奖励助学金,求出这些同学。
let englishClass = new Set(["鸣人", "路飞", "柯南"])
let mathClass = new Set(["小樱", "柯南", "鸣人"])
let sportClass = new Set(["鸣人", "艾伦"])

$$answer

$$jsdemo$$
$$edit$$
let englishClass = new Set(["鸣人", "路飞", "柯南"])
let mathClass = new Set(["小樱", "柯南", "鸣人"])
let sportClass = new Set(["鸣人", "艾伦"])

// 交集
function intersection(a, b) {
    let result = new Set()
    for (let x of b) {
        if (a.has(x)) {
            result.add(x)
        }
    }

    return result
}

let result = intersection(englishClass, mathClass)
result = intersection(sportClass, result)

console.log(result) // Set(1) {'鸣人'}

$$