数组去重的多种方式

这里每天分享一个 iOS 的新知识,快来关注我吧

前言

从数组中删除重复项是一项常见的任务,在 Swift 中,标准库没有直接提供一个系统函数给我们,必须自己实现这样的方法。

实现数组去重的方法有很多,今天来介绍一些常用的方法。

1、使用 Set 去重

Set 也是一个集合,只是它不包含重复项,利用这个特点,我们可以简单的给一个数组去重:

sql 复制代码
let array: [Int] = [1, 1, 3, 3, 2, 2]
let set: Set<Int> = Set(array)
print(set)

上边的代码会打印去重之后的 1, 2, 3,但结果也可能是 3, 1, 2,也可能是 3, 2, 1,这就涉及到 Set 的原始设计了,它内部的元素是无序的 ,不能保证固定的顺序,如果你对顺序有要求,就不能用 Set 来实现了。

2、巧用字典去重

我们都知道字典中是无法存储相同 Key 的,也就可以利用 Key 的唯一性来去重:

less 复制代码
let array: [Int] = [1, 1, 3, 3, 2, 2]
var dic: [Int: Int] = [:]
array.forEach { dic[$0] = 0 }
print(dic.keys)

先把 array 遍历一遍,所有元素作为字典的 key 存储起来,最后再取 dic.keys 获得去重之后的数组。

但是字典的 key 也一样是无序的,而且使用字典会带来额外的性能开销,因此不推荐这种方式。

上边提到这两种方案都无法保证顺序,如果需要保证去重后的顺序和原数组保持一致,请看下边的几个方案。

3、利用 NSOrderedSet

NSOrderedSet 是 OC 时代的产物,继承自 NSObject,它可以像 Set 一样实现去重,也可以保证顺序:

php 复制代码
let array: [Int] = [1, 1, 3, 3, 2, 2]
let orderSet = NSOrderedSet(array: array)
print(orderSet.array)

最终打印 1, 2, 3,顺序和原数组保持一致,但是需要注意这玩意性能比 Set 差很多。

4、遍历数组去重

这也是最符合直觉的方法,把数组遍历一遍,创建个新数组,如果这个元素没有加入新数组就加进去,如果加过了就抛掉:

less 复制代码
let array: [Int] = [1, 1, 3, 3, 2, 2]
var newArray: [Int] = []
array.forEach { item in
    if !newArray.contains(item) {
        newArray.append(item)
    }
}
print(newArray)

最终打印 1, 3, 2,也是保持顺序的。

为了更方便调用还可以将这个方法写个数组扩展:

javascript 复制代码
extension Array where Element: Hashable {
    var unique: Self {
        var newArray: Self = []
        forEach { ele in
            if !newArray.contains(ele) {
                newArray.append(ele)
            }
        }
        return newArray
    }
}

这样调用的时候就方便了:

php 复制代码
let array: [Int] = [1, 1, 3, 3, 2, 2]
print(array.unique) // [1, 3, 2]

5、filter 高阶函数 + Set

Set 在插入元素的时候调用 insert 函数,这个函数返回一个元组,第一个值是一个 Bool 类型代表是否插入成功,如果已经包含了这个元素则不能插入成功,另一个是被插入的这个元素,这在 Set 的函数声明中可以看得出来:

swift 复制代码
func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element)

我们可以利用这个特性,再加上 filter 这个高阶函数,来给集合 Array 写一个扩展:

swift 复制代码
extension Array where Element: Hashable {
    var unique: Self {
        var seen: Set<Element> = []
        return filter { seen.insert($0).inserted }
    }
}

调用方法和上边的方式一样。

点击下方公众号卡片,关注我,每天分享一个关于 iOS 的新知识

本文同步自微信公众号 "iOS新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
for_ever_love__17 分钟前
UI学习:UISearchController基础了解和应用
学习·ui·ios·objective-c
代码的小搬运工5 小时前
ZARA仿写
ios
人月神话Lee7 小时前
【图像处理】vImage/Accelerate——SIMD 让 CPU 也能飞
ios·swift·图像识别
2601_9557674210 小时前
iPhone 17 护眼钢化膜怎么选?从PWM频闪到圆偏振光,解析「软硬协同」光学方案
ios·ar·iphone·护眼钢化膜·圆偏振光·#观复盾护景贴·磁控溅射
2601_9557674213 小时前
iPhone 17 护眼保护膜怎么选?圆偏振光 + AR 抗眩方案,解读 96% 透光率与 ≤0.5% 反射率的协同价值
ios·ar·iphone·圆偏振光·#观复盾护景贴·scinique双护技术
三雒13 小时前
KMP 实战:Android 开发如何快速统一双端 IM 模块
android·ios·kotlin
秋雨梧桐叶落莳15 小时前
iOS——抽屉视图详解
开发语言·macos·ui·ios·objective-c·cocoa
库奇噜啦呼15 小时前
【iOS】源码学习-方法交换
学习·ios·cocoa
hurrycry_小亦1 天前
苹果WWDC 2026前瞻:Ferret-Pro端侧大模型即将亮相|小亦之闻|AI 编程三日速递!(5月26日~5月28日)
macos·ios·wwdc
UTF_81 天前
一次NSMutableAttributedString误用的思考
ios·面试·github