Set数据结构:存储唯一值集合 (ES6+)

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 }

注意,即使我们在数组中重复添加了 5Set 也会自动去重,只保留一个 5

Set 的常用方法

Set 提供了许多方便的方法来操作集合。下面我们来看看一些常用的 API:

方法名 描述 示例
add(value) Set 中添加一个新值。如果该值已经存在,则不会重复添加。 mySet.add(1)
delete(value) Set 中删除指定的值。返回 true 如果删除成功,否则返回 false mySet.delete(1)
has(value) 检查 Set 中是否包含指定的值。返回 truefalse 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 还引入了 WeakSetWeakSetSet 类似,但它只能存储对象,并且这些对象是弱引用的。这意味着如果 WeakSet 中的对象不再被其他变量引用,它们会被自动垃圾回收。

WeakSet 适用于那些不需要长期保存对象引用的场景,比如缓存或事件监听器。由于 WeakSet 的特殊性,它的 API 也相对较少,只有 adddeletehas 三个方法。

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 都是一个值得掌握的工具。

如果你还有任何问题,欢迎在评论区留言!下次见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注