数组去重的多种方式
前言
从数组中删除重复项是一项常见的任务,在 Swift 中,标准库没有直接提供一个系统函数给我们,必须自己实现这样的方法。
实现数组去重的方法有很多,今天来介绍一些常用的方法。
1、使用 Set 去重
Set
也是一个集合,只是它不包含重复项,利用这个特点,我们可以简单的给一个数组去重:
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
的唯一性来去重:
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 一样实现去重,也可以保证顺序:
let array: [Int] = [1, 1, 3, 3, 2, 2]
let orderSet = NSOrderedSet(array: array)
print(orderSet.array)
最终打印 [1, 2, 3],顺序和原数组保持一致,但是需要注意这玩意性能比 Set
差很多。
4、遍历数组去重
这也是最符合直觉的方法,把数组遍历一遍,创建个新数组,如果这个元素没有加入新数组就加进去,如果加过了就抛掉:
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],也是保持顺序的。
为了更方便调用还可以将这个方法写个数组扩展:
extension Array where Element: Hashable {
var unique: Self {
var newArray: Self = []
forEach { ele in
if !newArray.contains(ele) {
newArray.append(ele)
}
}
return newArray
}
}
这样调用的时候就方便了:
let array: [Int] = [1, 1, 3, 3, 2, 2]
print(array.unique) // [1, 3, 2]
5、filter 高阶函数 + Set
Set
在插入元素的时候调用 insert
函数,这个函数返回一个元组,第一个值是一个 Bool
类型代表是否插入成功,如果已经包含了这个元素则不能插入成功,另一个是被插入的这个元素,这在 Set
的函数声明中可以看得出来:
func insert(_ newMember: Element) -> (inserted: Bool, memberAfterInsert: Element)
我们可以利用这个特性,再加上 filter 这个高阶函数,来给集合 Array
写一个扩展:
extension Array where Element: Hashable {
var unique: Self {
var seen: Set<Element> = []
return filter { seen.insert($0).inserted }
}
}
调用方法和上边的方式一样。
链接:https://juejin.cn/post/7275943600771399699
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。