我可能有一个像下面这样的数组:
[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
或者,实际上,任何类似类型的数据部分的序列。我要做的是确保每个相同的元素只有一个。例如,上面的数组将变成:
[1, 4, 2, 6, 24, 15, 60]
请注意,删除了2、6和15的重复项,以确保每个相同的元素中只有一个。Swift是否提供了一种容易做到这一点的方法,还是我必须自己做?
我可能有一个像下面这样的数组:
[1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
或者,实际上,任何类似类型的数据部分的序列。我要做的是确保每个相同的元素只有一个。例如,上面的数组将变成:
[1, 4, 2, 6, 24, 15, 60]
请注意,删除了2、6和15的重复项,以确保每个相同的元素中只有一个。Swift是否提供了一种容易做到这一点的方法,还是我必须自己做?
当前回答
这只是一个非常简单和方便的实现。具有相等元素的数组扩展中的计算属性。
extension Array where Element: Equatable {
/// Array containing only _unique_ elements.
var unique: [Element] {
var result: [Element] = []
for element in self {
if !result.contains(element) {
result.append(element)
}
}
return result
}
}
其他回答
我使用了@Jean-Philippe Pellet的答案,并做了一个数组扩展,对数组进行类似set的操作,同时保持元素的顺序。
/// Extensions for performing set-like operations on lists, maintaining order
extension Array where Element: Hashable {
func unique() -> [Element] {
var seen: [Element:Bool] = [:]
return self.filter({ seen.updateValue(true, forKey: $0) == nil })
}
func subtract(takeAway: [Element]) -> [Element] {
let set = Set(takeAway)
return self.filter({ !set.contains($0) })
}
func intersect(with: [Element]) -> [Element] {
let set = Set(with)
return self.filter({ set.contains($0) })
}
}
Swift 3/ Swift 4/ Swift 5
只需要一行代码就可以省略数组副本而不影响顺序:
let filteredArr = Array(NSOrderedSet(array: yourArray))
包含相等性检查,而插入检查哈希,最安全的检查方式如下:
extension Array where Element: Hashable {
/// Big O(N) version. Updated since @Adrian's comment.
var uniques: Array {
// Go front to back, add element to buffer if it isn't a repeat.
var buffer: [Element] = []
var dictionary: [Element: Int] = [:]
for element in self where dictionary[element] == nil {
buffer.append(element)
dictionary[element] = 1
}
return buffer
}
}
如果你想保持秩序,那么就用这个
let fruits = ["apple", "pear", "pear", "banana", "apple"]
let orderedNoDuplicates = Array(NSOrderedSet(array: fruits).map({ $0 as! String }))
在Swift 3.0中,我发现了最简单和最快的解决方案,可以在保持顺序的同时消除重复的元素:
extension Array where Element:Hashable {
var unique: [Element] {
var set = Set<Element>() //the unique list kept in a Set for fast retrieval
var arrayOrdered = [Element]() //keeping the unique list of elements but ordered
for value in self {
if !set.contains(value) {
set.insert(value)
arrayOrdered.append(value)
}
}
return arrayOrdered
}
}