一个数组,要对元素进行去重操作有两种方式,要么重写equals方法做比较,要么利用Hash值做比较。
假设对象为点Point

1
2
3
4
struct Point {
let x: Int
let y: Int
}

让对象实现equals方法

1
2
3
4
5
extension Point: Equatable {
static func == (lhs: Point, rhs: Point) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
}

接着,我们对Array做扩展,新增去重方法并返回新数组:

1
2
3
4
5
6
7
8
9
10
11
extension Array where Element: Equatable {
func uniqueElements() -> [Element] {
var out = [Element]()
for element in self {
if !out.contains(element) {
out.append(element)
}
}
return out
}
}

用Hash值方式比较对象

把元素对象放至Set无序集合中,由于Set根据Hash值来存储,可存储唯一Hash值对象保证不重复。准备一个空数组接收。

1
extension Point: Hashable {}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
extension Array where Element: Hashable {
func uniqueElements() -> [Element] {
var seen = Set<Element>()
var out = [Element]()

for element in self {
if !seen.contains(element) {
out.append(element)
seen.insert(element)
}
}

return out
}
}

将代码用compactMap改进一下:遍历每一个元素并返回不为nil的元素。我们根据元素是否存在Set集合中为条件,当存在集合中时返回nil。
1
2
3
4
5
6
7
8
9
10
11
12
13
extension Array where Element: Hashable {
func uniqueElements() -> [Element] {
var seen = Set<Element>()

return self.compactMap { element in
guard !seen.contains(element)
else { return nil }

seen.insert(element)
return element
}
}
}

当我们不考虑原元素对象顺序的情况下,可以快速对元素去重
1
2
3
4
5
6
extension Array where Element: Hashable {
func unsortedUniqueElements() -> [Element] {
let set = Set(self)
return Array(set)
}
}

评论