for...of循环遍历Set时,如何删除元素?

简介: for...of循环遍历Set时,如何删除元素?

在使用 for...of 循环遍历 Set 时删除元素需要特别小心,因为直接在遍历过程中修改 Set 的结构可能会导致意外结果(如跳过元素或引发错误)。以下是几种安全的删除方法及注意事项:

一、错误示例:直接在循环中删除当前元素

const set = new Set([1, 2, 3, 4]);
for (const num of set) {
   
  if (num > 2) {
   
    set.delete(num); // 错误:可能跳过元素
  }
}
console.log([...set]); // 输出: [1, 3](3 未被删除!)

问题原因
删除元素后,Set 的内部迭代器位置可能发生变化,导致某些元素被跳过。

二、安全方法:先收集待删除元素,再批量删除

步骤

  1. 遍历 Set,将需要删除的元素存入临时数组。
  2. 遍历临时数组,批量删除元素。
const set = new Set([1, 2, 3, 4]);
const toDelete = [];

// 第一步:收集需要删除的元素
for (const num of set) {
   
  if (num > 2) {
   
    toDelete.push(num);
  }
}

// 第二步:批量删除
toDelete.forEach(num => set.delete(num));

console.log([...set]); // 输出: [1, 2]

三、转换为数组后遍历删除

步骤

  1. 将 Set 转换为数组(如 [...set])。
  2. 遍历数组,使用原 Set 的 delete 方法删除元素。
const set = new Set([1, 2, 3, 4]);

[...set].forEach(num => {
   
  if (num > 2) {
   
    set.delete(num); // 安全:操作的是原 Set,但遍历的是副本
  }
});

console.log([...set]); // 输出: [1, 2]

四、使用 while 循环手动控制迭代

步骤

  1. 获取 Set 的迭代器
  2. 手动调用 next(),在删除元素后重置迭代器或继续处理。
const set = new Set([1, 2, 3, 4]);
const iterator = set[Symbol.iterator]();

let result;
while ((result = iterator.next()) && !result.done) {
   
  const num = result.value;
  if (num > 2) {
   
    set.delete(num); // 删除当前元素
    // 注意:此处迭代器可能已失效,需重新获取或跳过逻辑
  }
}

console.log([...set]); // 输出: [1, 2]

五、注意事项与最佳实践

  1. 避免在 for...of 中直接删除
    直接删除会导致迭代器状态异常,优先选择批量删除或转换为数组操作。

  2. 性能考虑

    • 若 Set 较大,批量删除(方法二)可能比转换为数组(方法三)更高效,因为避免了创建临时数组。
  3. 删除后重置迭代器
    在手动控制迭代(方法四)时,删除元素后需谨慎处理迭代器,可能需要重新获取迭代器或调整循环逻辑。

  4. 适用场景

    • 批量删除:方法二或方法三。
    • 复杂条件删除:结合 Array.filter() 或手动迭代(方法四)。

总结

安全删除 Set 元素的核心原则是:避免在遍历原 Set 的同时修改其结构。通过临时存储待删除元素或转换为数组,可以有效规避迭代器异常问题。

相关文章
|
1月前
|
存储 安全
for...of循环在遍历Set时,如何正确添加元素?
for...of循环在遍历Set时,如何正确添加元素?
137 59
|
1月前
|
存储 安全 JavaScript
如何在不影响遍历的情况下从Set中删除元素?
如何在不影响遍历的情况下从Set中删除元素?
133 58
|
1月前
|
存储 安全 JavaScript
如何使用Set的delete()方法删除元素?
如何使用Set的delete()方法删除元素?
122 10
|
1月前
|
存储 JavaScript 前端开发
for...of循环在遍历Set和Map时的注意事项有哪些?
for...of循环在遍历Set和Map时的注意事项有哪些?
48 0
|
8月前
|
Java 开发者
从 Java 中的 Set 集合中删除元素
【10月更文挑战第30天】
|
安全 Java 流计算
【小家java】Java中集合List、Set、Map删除元素的方法大总结(避免ConcurrentModificationException异常)(下)
【小家java】Java中集合List、Set、Map删除元素的方法大总结(避免ConcurrentModificationException异常)(下)
【小家java】Java中集合List、Set、Map删除元素的方法大总结(避免ConcurrentModificationException异常)(下)
|
算法 Java 索引
【小家java】Java中集合List、Set、Map删除元素的方法大总结(避免ConcurrentModificationException异常)(上)
【小家java】Java中集合List、Set、Map删除元素的方法大总结(避免ConcurrentModificationException异常)(上)
|
4月前
|
编译器 C++ 容器
【c++丨STL】基于红黑树模拟实现set和map(附源码)
本文基于红黑树的实现,模拟了STL中的`set`和`map`容器。通过封装同一棵红黑树并进行适配修改,实现了两种容器的功能。主要步骤包括:1) 修改红黑树节点结构以支持不同数据类型;2) 使用仿函数适配键值比较逻辑;3) 实现双向迭代器支持遍历操作;4) 封装`insert`、`find`等接口,并为`map`实现`operator[]`。最终,通过测试代码验证了功能的正确性。此实现减少了代码冗余,展示了模板与仿函数的强大灵活性。
110 2
|
1月前
|
存储 C++ 容器
unordered_set、unordered_multiset、unordered_map、unordered_multimap的介绍及使用
unordered_set是不按特定顺序存储键值的关联式容器,其允许通过键值快速的索引到对应的元素。在unordered_set中,元素的值同时也是唯一地标识它的key。在内部,unordered_set中的元素没有按照任何特定的顺序排序,为了能在常数范围内找到指定的key,unordered_set将相同哈希值的键值放在相同的桶中。unordered_set容器通过key访问单个元素要比set快,但它通常在遍历元素子集的范围迭代方面效率较低。它的迭代器至少是前向迭代器。前向迭代器的特性。
64 0
|
1月前
|
编译器 C++ 容器
用一棵红黑树同时封装出map和set
再完成上面的代码后,我们的底层代码已经完成了,这时候已经是一个底层STL的红黑树了,已经已符合库里面的要求了,这时候我们是需要给他穿上对应的“衣服”,比如穿上set的“衣服”,那么这个穿上set的“衣服”,那么他就符合库里面set的要求了,同样map一样,这时候我们就需要实现set与map了。因此,上层容器map需要向底层红黑树提供一个仿函数,用于获取T当中的键值Key,这样一来,当底层红黑树当中需要比较两个结点的键值时,就可以通过这个仿函数来获取T当中的键值了。我们就可以使用仿函数了。
28 0