Set
一直以来,JS 只能使用数据和对象来保存多个数据,缺乏其他语言那样拥有丰富的集合类型。因此,在 ES6 新增了两种集合类型(Set 和 Map),用于在不同的场景中发挥作用。
Set 用于存放不重复的数据
1. 如何创建 set 集合
javascript
// 创建了一个空的set集合
let mySet = new Set()
javascript
// 创建了一个具有初始内容的set集合,内容来自于可迭代对象每一次迭代的结果
let mySet = new Set(iterable)
2. 如何对 set 集合进行操作
- add: 添加一个数据到 set 集合的末尾,如果数据已存在,则不进行任何操作。
- set 使用
Object.is的方式判断数据是否相同
。 - 特殊情况:针对+0 和-0 的情况,是相同的。
- set 使用
- has: 判断 set 中是否存在对应的数据
- delete: 从 set 集合中删除对应的数据,如果数据不存在,则不进行任何操作。
- clear: 清空 set 集合
- size: 获取 set 集合的长度
3. 如何与数组进行相互转换
javascript
const s = new Set([1, 2, 3, 4, 5])
// set 本身也是一个可迭代对象,每次迭代的结果就是每一项的值
const arr = [...s]
去重
javascript
const arr = [22, 11, 33, 42, 21, 43, 55, 33]
const result = [...new Set(arr)]
console.log(result) // [22, 11, 33, 42, 21, 43, 55]
const str = 'aassqweerqqffoopp'
const s = new Set(str).join('')
console.log(s) // ['a', 's', 'q', 'w', 'e', 'r', 'o', 'p']
4. 如果遍历
4.1 for...of 遍历
4.2 set 方法携带的 forEach 方法遍历
注意:set 集合中不存在下标,因此 forEach 中的回调的第二个参数和第一个参数是一致的,均表示 set 中的每一项。
javascript
const s = new Set([1, 2, 3, 4, 5])
s.forEach((item, item2, s) => {
console.log(item, item, s)
})
5. 应用
求两个数组的并集、交集、差集
javascript
const arr1 = [1, 3, 4, 5, 5, 9, 9]
const arr2 = [1, 2, 4, 5, 6, 7, 8]
// 并集
const union = new Set([...arr1, ...arr2])
console.log(union) // Set(9) {1, 2, 3, 4, 5, 6, 7, 8, 9}
// 交集
const intersection = new Set(arr1.filter((x) => arr2.includes(x)))
console.log(intersection) // Set(3) {1, 4, 5}
// 差集
const difference = [...new Set([...arr1, ...arr2])].filter(
(x) =>
(arr1.includes(x) && !arr2.includes(x)) ||
(!arr1.includes(x) && arr2.includes(x))
)
console.log(difference) // Set(6) {3, 9}
6. 手写 Set
模拟 Set 的实现
javascript
class MySet {
constructor(iterator) {
// 验证是否是可迭代对象
if (typeof iterator[Symbol.iterator] !== 'function') {
throw new TypeError(`你提供的${iterator}不是一个可迭代的对象`)
}
this._datas = []
for (let item of iterator) {
this.add(item)
}
}
add(data) {
if (!this.has(data)) {
this._datas.push(data)
}
}
has(data) {
for (let item of this._datas) {
if (this.isEqual(data, item)) {
return true
}
return false
}
}
delete(data) {
for (let i = 0; i < this._datas.length; i++) {
const element = this._datas[i]
if (this.isEqual(data, element)) {
this._datas.splice(i, 1)
return true
}
}
return false
}
clear() {
this._datas.length = 0
}
forEach(callback) {
for (let item of this._datas) {
callback(item, item, this)
}
}
// 将该对象转变成可以迭代的对象
*[Symbol.iterator]() {
for (let item of this._datas) {
yield item
}
}
isEqual(data1, data2) {
if (data1 === 0 && data2 === 0) {
return true
}
return Object.is(data1, data2)
}
}