我可能有一个像下面这样的数组:
[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 {
func containsHowMany(_ elem: Element) -> Int {
return reduce(0) { $1 == elem ? $0 + 1 : $0 }
}
func duplicatesRemoved() -> Array {
return self.filter { self.containsHowMany($0) == 1 }
}
mutating func removeDuplicates() {
self = self.duplicatesRemoved(()
}
}
您可以使用duplicatesRemoved()来获取一个新数组,它的重复元素将被删除,或者使用removeduplicate()来改变自身。看到的:
let arr = [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]
let noDuplicates = arr.duplicatesRemoved()
print(arr) // [1, 1, 1, 2, 2, 3, 4, 5, 6, 6, 6, 6, 6, 7, 8]
print(noDuplicates) // [1, 2, 3, 4, 5, 6, 7, 8]
arr.removeDuplicates()
print(arr) // [1, 2, 3, 4, 5, 6, 7, 8]
其他回答
你可以自己卷,比如这样:
func unique<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
let vals = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let uniqueVals = uniq(vals) // [1, 4, 2, 6, 24, 15, 60]
作为Array的扩展:
extension Array where Element: Hashable {
func uniqued() -> Array {
var buffer = Array()
var added = Set<Element>()
for elem in self {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
}
或者更优雅一点(Swift 4/5):
extension Sequence where Element: Hashable {
func uniqued() -> [Element] {
var set = Set<Element>()
return filter { set.insert($0).inserted }
}
}
将被使用:
[1,2,4,2,1].uniqued() // => [1,2,4]
包含相等性检查,而插入检查哈希,最安全的检查方式如下:
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
}
}
这里有一个解决方案
不使用传统NS类型 对于O(n)来说是相当快的 简洁 保持元素顺序
extension Array where Element: Hashable {
var uniqueValues: [Element] {
var allowed = Set(self)
return compactMap { allowed.remove($0) }
}
}
斯威夫特5.7
使用有序集
您可以将具有重复元素的数组传递给以下通用函数,该函数处理有序Set并返回没有重复元素的新数组。
import Foundation
internal func withoutDuplicates<T>(_ array: [T]) -> [T] {
let orderedSet: NSMutableOrderedSet = []
var modifiedArray = [T]()
orderedSet.addObjects(from: array)
for i in 0...(orderedSet.count - 1) {
modifiedArray.append(orderedSet[i] as! T)
}
return modifiedArray
}
////////////////////////////////////////////////////////////
let arrayOfStrings: [String] = ["A","A","A","B","B","C","C"]
let arrayOfIntegers: [UInt8] = [1, 1, 1, 2, 2, 2, 3, 3]
let arrayOfBooleans: [Bool] = [true, false, false, true]
let ordered_01 = withoutDuplicates(arrayOfStrings)
let ordered_02 = withoutDuplicates(arrayOfIntegers)
let ordered_03 = withoutDuplicates(arrayOfBooleans)
结果:
// ordered_01 –––> ["A","B","C"]
// ordered_02 –––> [1, 2, 3]
// ordered_03 –––> [true, false]
使用无序集
如果新数组中元素的顺序对您来说并不重要,则在处理时使用无序集。无序集中的元素类型必须符合哈希协议。
import UIKit
fileprivate func noDuplicates<T: Hashable>(_ array: [T]) -> [T] {
var unorderedSet = Set<T>()
var modifiedArray: [T] = []
for i in 0...(array.count - 1) {
unorderedSet.insert(array[i])
}
for i in unorderedSet.indices {
modifiedArray.append(unorderedSet[i])
}
return modifiedArray
}
////////////////////////////////////////////////////////////
let arrayOfInts: [Int] = [10, 5, 7, 200, -500, 10, 7, 5]
let arrayOfStrs: [String] = ["A","A","A","B","B","C","C"]
let arrayOfBools: [Bool] = [true, false, false, true]
let unordered_01 = noDuplicates(arrayOfInts)
let unordered_02 = noDuplicates(arrayOfStrs)
let unordered_03 = noDuplicates(arrayOfBools)
结果:
// unordered_01 –––> [200, 7, 10, -500, 5]
// unordered_02 –––> ["B", "C", "A"]
// unordered_03 –––> [false, true]
首先将数组的所有元素添加到NSOrderedSet中。 这将删除数组中的所有重复项。 再次将这个orderedset转换为一个数组。
做……
例子
let array = [1,1,1,1,2,2,2,2,4,6,8]
let orderedSet : NSOrderedSet = NSOrderedSet(array: array)
let arrayWithoutDuplicates : NSArray = orderedSet.array as NSArray
输出arraywithoutduplates - [1,2,4,6,8]