# 集合(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
}
}
# 并集
对于给定的两个集合,返回一个包含两个集合中所有元素的新集合。
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]
注意元素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]
改进交集方法
假设我们有下面两个集合:
- 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
}
# 差集
对于给定的两个集合,返回一个包含所有存在于第一个集合且不存在于第二个集合的元素的新集合。
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]
# 子集
验证一个给定集合是否是另一集合的子集。
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
我们有三个集合:setA
是setB
的子集(因此输出为true),然而setA
不是setC
的子集(setC
只包含了setA
中的2,而不包含1),因此输出为false。