You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

遍历Set数据结构时删除元素是否安全?

遍历Set时删除元素是否安全?

我们都知道遍历数组时直接删除元素是不安全的,比如这段代码必然崩溃:

var datas = ["X", "Y", "Z", "1", "2", "3"]

for (index, data) in datas.enumerated() {
    if data == "Y" || data == "Z" || data == "3" {
        datas.remove(at: index)    // Crash!
    }
}

原因很简单:删除元素会导致数组后续元素前移,索引和元素的对应关系错乱,最终触发数组越界。

那回到Set的场景:你测试的代码没出现崩溃,但这不代表这种操作是安全的,背后藏着不少潜在问题:

为什么当前代码没崩溃?

Swift的Set基于哈希表实现,遍历会生成一个迭代器指向当前哈希表的元素。如果删除操作没触发哈希表的结构重组(比如扩容、缩容、重新哈希),迭代器可能还能正常工作,不会立刻崩溃。但这只是巧合,不是必然结果。

可能引发的问题

  • 元素漏处理或重复遍历:一旦删除操作触发哈希表结构变化,迭代器可能跳过某些元素,导致本该删除的元素没被处理;或者哈希表重组后,部分元素被迭代器多次访问。
  • 未定义行为:Swift官方明确说明,遍历集合(包括Set)时修改集合,迭代器的行为是未定义的——不同Swift版本、不同元素数量、不同哈希分布,都可能导致不同结果,比如突然崩溃、数据错乱。
  • 隐性bug:这类问题不是必现的,测试环境可能正常,生产环境才触发,排查起来极其麻烦。

安全的处理方式

推荐两种稳妥的写法:

  1. 遍历Set的副本:先创建原Set的副本,遍历副本时修改原Set:
var datas = Set(["X", "Y", "Z", "1", "2", "3"])
for data in Array(datas) {
    if data == "Y" || data == "Z" || data == "3" {
        datas.remove(data)
    }
}
  1. 用filter生成新Set:更简洁的Swift风格,直接过滤出需要保留的元素替换原Set:
var datas = Set(["X", "Y", "Z", "1", "2", "3"])
datas = datas.filter { !["Y", "Z", "3"].contains($0) }

内容的提问来源于stack exchange,提问作者Cheok Yan Cheng

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 07:07:31