Swift:移除数组中的重复元素

引子

从数组中去除重复项用来获取唯一值,在日常开发中是一项常见的操作。像 Ruby 这样的语言有内置的 uniq 方法,但在 Swift 中,我们必须自己创建这样的方法。标准库并没有提供一个简单的实现此功能的方法。

有多种方法可以达到相同的结果,每种方法都有其自身的优点和缺点。让我们一起来探讨一下,看看哪种方法最适合你的应用场景。

通过 Set 来去除重复元素

在我们开始探讨如何对数组中的重复项进行删除的扩展操作之前,先了解一下 Swift 中的 Set 是个不错的选择。默认情况下,集合只会包含唯一的值,这样就可以满足我们需要的效果。

如果我们选择使用 Set 来实现的话,有两个注意点:

  • 我们不需要元素有序。
  • 每个元素都是唯一的。
swift 复制代码
let arrayOfnums: [Int] = [1, 1, 2, 2, 3, 3]
let setOfNums: Set<Int> = [1, 1, 1, 2, 2, 2, 3, 3, 3]

print(arrayOfnums) // [1, 1, 2, 2, 3, 3]
print(setOfNums)   // [2, 3, 1]

这更多地属于一种代码设计决策,即你需要选择使用集合(Set)还是数组(Array)。集合的一个优点是性能更优,这使得它们成为解决唯一性问题的绝佳选择。

无需过多详述其差异所在,但要知道集合并不会保持元素的顺序。如果在你的需求是必须保持元素顺序,那么你可能就不应选择使用集合。

你可以选择使用 NSOrderedSet,但这个类无法提供类型补全功能,你将不得不处理 Any 的实例。

通过给数组添加扩展函数来实现去重

当元素的顺序至关重要时,我们可以继续使用数组,并通过使用自定义扩展来获取唯一的值。

如果要使用数组的话:

  • 顺序很重要
  • 你不能轻易切换到一个集合

我们需要创建一个扩展来过滤掉重复的元素。在设计这个扩展时,务必考虑到性能问题,因为如果我们不注意这一点,很快就会出现 O(N²) 的二次时间复杂度。

简而言之,这意味着你拥有的元素越多,性能就会越差。以下这段代码依赖于 Hashable 协议来匹配元素,并且其时间复杂度为线性的 O(N)。这意味着 3 个元素需要 3 次迭代,10 个元素需要 10 次迭代,以此类推。示例代码如下:

dart 复制代码
extension Sequence where Iterator.Element: Hashable {
    func unique() -> [Iterator.Element] {
        var seen: Set<Iterator.Element> = []
        return filter { seen.insert($0).inserted }
    }
}

print(arrayOfnums.unique()) // [1, 2, 3]

让我们来剖析一下这个 unique() 方法:

  • 我们创建一个集合来跟踪已查看的对象
  • 使用一个过滤器来遍历所有对象
  • insert(_:) 方法会返回一个包含一个插入布尔值的元组,如果对象被插入则该布尔值设为 true,否则设为 false
  • 插入的布尔值值用于从我们的数组中过滤掉重复项

最终结果是一个顺序相同但没有重复元素的数组。唯一的缺点是数组的元素需要符合 Hashable 协议,但这应该不是什么大问题。标准库中的许多类型(如字符串、整数和布尔值)都已符合该协议。Hashable 用于确定一个元素是否与现有对象相等,因此是获取唯一值所必需的。

相关推荐
大熊猫侯佩3 天前
Xcode 预览新升级:arguments 让界面调试井井有条
swiftui·xcode·swift
做前端的娜娜子3 天前
文档加载工程:多格式数据接入与 Document 标准化
langchain·ai编程·掘金·金石计划
大熊猫侯佩4 天前
WWDC26:把 SwiftUI Toolbar 真正握在手心里
swiftui·swift·apple
做前端的娜娜子4 天前
Embedding 向量模型:从语义表示到相似度计算
langchain·openai·掘金·金石计划
做前端的娜娜子4 天前
第二个 AI 调用——invoke 阻塞式与 stream 流式生成
人工智能·llm·掘金·金石计划
大熊猫侯佩4 天前
WWDC 26 全新 ResultsObserver:终于能在 View 外面盯着 SwiftData 了
swiftui·swift·apple
大熊猫侯佩4 天前
别再把大模型供在云端了,WWDC26 CoreAI 大模型下凡实战
ai编程·swift·wwdc
00后程序员张4 天前
有没有更轻量的 iOS 开发环境?快蝎kxapp轻量化路径与构成
ide·vscode·ios·objective-c·个人开发·swift·敏捷流程
做前端的娜娜子5 天前
第一个AI调用——TypeScript 工程初始化与配置管理(实战跟练)
langchain·openai·掘金·金石计划
sakiko_5 天前
Swift学习笔记39-实战注意事项
前端·笔记·学习·swift