数组去重的多种方式

这里每天分享一个 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新知",每天准时分享一个新知识,这里只是同步,想要及时学到就来关注我吧!

相关推荐
开心就好20253 小时前
iOS App 安全加固流程记录,代码、资源与安装包保护
后端·ios
开心就好20253 小时前
iOS App 性能测试工具怎么选?使用克魔助手(Keymob)结合 Instruments 完成
后端·ios
zhongjiahao1 天前
面试常问的 RunLoop,到底在Loop什么?
ios
wvy2 天前
iOS 26手势返回到根页面时TabBar的动效问题
ios
RickeyBoy2 天前
iOS 图片取色完全指南:从像素格式到工程实践
ios
aiopencode3 天前
使用 Ipa Guard 命令行版本将 IPA 混淆接入自动化流程
后端·ios
二流小码农3 天前
鸿蒙开发:路由组件升级,支持页面一键创建
android·ios·harmonyos
iceiceiceice4 天前
iOS PDF阅读器段评实现:如何从 PDFSelection 精准还原一个自然段
前端·人工智能·ios
TT_Close4 天前
【Flutter×鸿蒙】FVM 不认鸿蒙 SDK?4步手动塞进去
flutter·swift·harmonyos
张江4 天前
Swift Concurrency学习
swift