我可能有一个像下面这样的数组:
[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是否提供了一种容易做到这一点的方法,还是我必须自己做?
当前回答
斯威夫特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]
其他回答
现在不需要写扩展了。
Apple终于在其算法包中引入了unique()方法,可以在符合Sequence协议的任何类型上使用。
import Algorithms
let numbers = [1, 2, 3, 3, 2, 3, 3, 2, 2, 2, 1]
print(numbers.uniqued()) // prints [1, 2, 3]
更多信息https://github.com/apple/swift-algorithms/blob/main/Guides/Unique.md
从数组中删除重复项的另一个Swift 3.0解决方案。该解决方案改进了许多已经提出的其他解决方案:
保留输入数组中元素的顺序 线性复杂度O(n):单通滤波器O(n) +集插入O(1)
给定整数数组:
let numberArray = [10, 1, 2, 3, 2, 1, 15, 4, 5, 6, 7, 3, 2, 12, 2, 5, 5, 6, 10, 7, 8, 3, 3, 45, 5, 15, 6, 7, 8, 7]
功能代码:
func orderedSet<T: Hashable>(array: Array<T>) -> Array<T> {
var unique = Set<T>()
return array.filter { element in
return unique.insert(element).inserted
}
}
orderedSet(array: numberArray) // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]
数组扩展代码:
extension Array where Element:Hashable {
var orderedSet: Array {
var unique = Set<Element>()
return filter { element in
return unique.insert(element).inserted
}
}
}
numberArray.orderedSet // [10, 1, 2, 3, 15, 4, 5, 6, 7, 12, 8, 45]
这段代码利用了Set上的插入操作返回的结果,该操作在O(1)上执行,并返回一个元组,指示该项是否被插入,或者该项是否已经存在于Set中。
如果项目在集合中,过滤器将从最终结果中排除它。
斯威夫特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]
您总是可以使用Dictionary,因为Dictionary只能保存惟一的值。例如:
var arrayOfDates: NSArray = ["15/04/01","15/04/01","15/04/02","15/04/02","15/04/03","15/04/03","15/04/03"]
var datesOnlyDict = NSMutableDictionary()
var x = Int()
for (x=0;x<(arrayOfDates.count);x++) {
let date = arrayOfDates[x] as String
datesOnlyDict.setValue("foo", forKey: date)
}
let uniqueDatesArray: NSArray = datesOnlyDict.allKeys // uniqueDatesArray = ["15/04/01", "15/04/03", "15/04/02"]
println(uniqueDatesArray.count) // = 3
正如你所看到的,生成的数组并不总是按“顺序”排列。如果你想对数组排序,添加这个:
var sortedArray = sorted(datesOnlyArray) {
(obj1, obj2) in
let p1 = obj1 as String
let p2 = obj2 as String
return p1 < p2
}
println(sortedArray) // = ["15/04/01", "15/04/02", "15/04/03"]
.
使用Set或NSOrderedSet删除重复项,然后转换回数组:
let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))