Set 数据结构:存储唯一值集合 (ES6+)
欢迎来到 JavaScript Set 讲座
大家好,欢迎来到今天的讲座!今天我们要聊的是 ES6 中引入的一个非常有用的数据结构——Set
。如果你还不熟悉 Set
,或者只是想复习一下,那么你来对地方了!我们将会用轻松诙谐的语言,结合代码示例,带你深入了解 Set
的工作原理和使用方法。
什么是 Set?
简单来说,Set
是一个存储唯一值的集合。它与数组类似,但有一个关键的区别:Set
中的每个值都是唯一的,不能重复。这使得 Set
在处理去重、集合运算等场景时非常有用。
在 ES6 之前,JavaScript 并没有原生的 Set
数据结构,开发者通常需要自己编写代码来实现去重功能。而现在,有了 Set
,一切都变得简单多了!
创建 Set
创建 Set
非常简单,只需要调用 new Set()
即可。你可以传入一个可迭代对象(如数组)来初始化 Set
,或者直接创建一个空的 Set
。
// 创建一个空的 Set
const emptySet = new Set();
console.log(emptySet); // Set(0) {}
// 使用数组初始化 Set
const numbers = [1, 2, 3, 4, 5, 5, 5];
const numberSet = new Set(numbers);
console.log(numberSet); // Set(5) { 1, 2, 3, 4, 5 }
注意,即使我们在数组中重复添加了 5
,Set
也会自动去重,只保留一个 5
。
Set 的常用方法
Set
提供了许多方便的方法来操作集合。下面我们来看看一些常用的 API:
方法名 | 描述 | 示例 |
---|---|---|
add(value) |
向 Set 中添加一个新值。如果该值已经存在,则不会重复添加。 |
mySet.add(1) |
delete(value) |
从 Set 中删除指定的值。返回 true 如果删除成功,否则返回 false 。 |
mySet.delete(1) |
has(value) |
检查 Set 中是否包含指定的值。返回 true 或 false 。 |
mySet.has(1) |
clear() |
清空 Set ,移除所有元素。 |
mySet.clear() |
size |
返回 Set 中元素的数量。 |
console.log(mySet.size) |
forEach(callback) |
遍历 Set 中的每一个元素,执行回调函数。 |
mySet.forEach(value => console.log(value)) |
代码示例
const mySet = new Set();
// 添加元素
mySet.add(1);
mySet.add(2);
mySet.add(3);
console.log(mySet); // Set(3) { 1, 2, 3 }
// 检查是否存在某个值
console.log(mySet.has(2)); // true
console.log(mySet.has(4)); // false
// 删除元素
mySet.delete(2);
console.log(mySet); // Set(2) { 1, 3 }
// 获取 Set 的大小
console.log(mySet.size); // 2
// 清空 Set
mySet.clear();
console.log(mySet); // Set(0) {}
Set 的遍历
除了使用 forEach
方法遍历 Set
,你还可以使用 for...of
循环来遍历 Set
中的每一个元素。这种方式更加灵活,适合需要更多控制的场景。
const fruits = new Set(['apple', 'banana', 'orange']);
// 使用 for...of 遍历 Set
for (const fruit of fruits) {
console.log(fruit);
}
// 输出:
// apple
// banana
// orange
此外,Set
还提供了几个迭代器方法,可以帮助你更方便地操作集合:
keys()
:返回一个包含Set
中所有键的迭代器(实际上就是值本身,因为Set
中的键和值是相同的)。values()
:返回一个包含Set
中所有值的迭代器(与keys()
相同)。entries()
:返回一个包含[value, value]
形式的键值对的迭代器。
const letters = new Set(['a', 'b', 'c']);
// 使用 entries() 遍历键值对
for (const [key, value] of letters.entries()) {
console.log(key, value);
}
// 输出:
// a a
// b b
// c c
Set 的应用场景
Set
的最大优势在于它可以轻松处理唯一值,因此在很多场景下都非常有用。下面我们来看看一些常见的应用场景:
1. 数组去重
Set
最常见的用途之一就是去除数组中的重复元素。由于 Set
只允许存储唯一值,因此我们可以利用它来快速去重。
const numbers = [1, 2, 2, 3, 4, 4, 5];
const uniqueNumbers = [...new Set(numbers)];
console.log(uniqueNumbers); // [1, 2, 3, 4, 5]
2. 集合运算
Set
还可以用来进行集合运算,比如并集、交集、差集等。虽然 JavaScript 没有内置的集合运算方法,但我们可以通过简单的代码实现这些功能。
并集(Union)
并集是指两个集合中所有不重复的元素。我们可以通过将两个 Set
合并为一个新的 Set
来实现并集。
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);
const union = new Set([...setA, ...setB]);
console.log(union); // Set(5) { 1, 2, 3, 4, 5 }
交集(Intersection)
交集是指两个集合中都存在的元素。我们可以通过过滤 Set
来实现交集。
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);
const intersection = new Set([...setA].filter(x => setB.has(x)));
console.log(intersection); // Set(1) { 3 }
差集(Difference)
差集是指属于第一个集合但不属于第二个集合的元素。我们可以通过过滤 Set
来实现差集。
const setA = new Set([1, 2, 3]);
const setB = new Set([3, 4, 5]);
const difference = new Set([...setA].filter(x => !setB.has(x)));
console.log(difference); // Set(2) { 1, 2 }
3. 检查重复项
Set
还可以用来检查数组中是否有重复项。通过比较数组的长度和 Set
的大小,我们可以轻松判断数组中是否存在重复元素。
function hasDuplicates(arr) {
return new Set(arr).size !== arr.length;
}
console.log(hasDuplicates([1, 2, 3])); // false
console.log(hasDuplicates([1, 2, 2, 3])); // true
WeakSet:Set 的“弱”版本
除了 Set
,ES6 还引入了 WeakSet
。WeakSet
与 Set
类似,但它只能存储对象,并且这些对象是弱引用的。这意味着如果 WeakSet
中的对象不再被其他变量引用,它们会被自动垃圾回收。
WeakSet
适用于那些不需要长期保存对象引用的场景,比如缓存或事件监听器。由于 WeakSet
的特殊性,它的 API 也相对较少,只有 add
、delete
和 has
三个方法。
const weakSet = new WeakSet();
const obj1 = {};
const obj2 = {};
weakSet.add(obj1);
weakSet.add(obj2);
console.log(weakSet.has(obj1)); // true
console.log(weakSet.has(obj2)); // true
// 当 obj1 和 obj2 不再被引用时,它们会被自动垃圾回收
obj1 = null;
obj2 = null;
// 此时 weakSet 中的元素也会被移除
总结
好了,今天的讲座就到这里!通过这次学习,你应该对 Set
有了更深入的了解。Set
是一个非常强大且易用的数据结构,特别适合处理唯一值和集合运算。无论你是初学者还是经验丰富的开发者,Set
都是一个值得掌握的工具。
如果你还有任何问题,欢迎在评论区留言!下次见!