我可能有一个像下面这样的数组:
[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是否提供了一种容易做到这一点的方法,还是我必须自己做?
当前回答
斯威夫特4. x:
extension Sequence where Iterator.Element: Hashable {
func unique() -> [Iterator.Element] {
return Array(Set<Iterator.Element>(self))
}
func uniqueOrdered() -> [Iterator.Element] {
return reduce([Iterator.Element]()) { $0.contains($1) ? $0 : $0 + [$1] }
}
}
用法:
["Ljubljana", "London", "Los Angeles", "Ljubljana"].unique()
or
["Ljubljana", "London", "Los Angeles", "Ljubljana"].uniqueOrdered()
其他回答
使用Set或NSOrderedSet删除重复项,然后转换回数组:
let uniqueUnordered = Array(Set(array))
let uniqueOrdered = Array(NSOrderedSet(array: array))
编辑/更新Swift 4或更高版本
我们还可以扩展RangeReplaceableCollection协议,以允许它也用于StringProtocol类型:
extension RangeReplaceableCollection where Element: Hashable {
var orderedSet: Self {
var set = Set<Element>()
return filter { set.insert($0).inserted }
}
mutating func removeDuplicates() {
var set = Set<Element>()
removeAll { !set.insert($0).inserted }
}
}
let integers = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
let integersOrderedSet = integers.orderedSet // [1, 4, 2, 6, 24, 15, 60]
"abcdefabcghi".orderedSet // "abcdefghi"
"abcdefabcghi".dropFirst(3).orderedSet // "defabcghi"
变异的方法:
var string = "abcdefabcghi"
string.removeDuplicates()
string // "abcdefghi"
var substring = "abcdefabcdefghi".dropFirst(3) // "defabcdefghi"
substring.removeDuplicates()
substring // "defabcghi"
对于Swift 3,请点击这里
您可以直接使用set集合删除重复,然后将其转换回数组
var myArray = [1, 4, 2, 2, 6, 24, 15, 2, 60, 15, 6]
var mySet = Set<Int>(myArray)
myArray = Array(mySet) // [2, 4, 60, 6, 15, 24, 1]
然后你可以按你想要的顺序排列你的数组
myArray.sort{$0 < $1} // [1, 2, 4, 6, 15, 24, 60]
从数组中删除重复项的另一个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中。
如果项目在集合中,过滤器将从最终结果中排除它。
如果你把两个扩展都放在你的代码中,更快的Hashable版本将在可能的情况下使用,Equatable版本将用作备用版本。
public extension Sequence where Element: Hashable {
/// The elements of the sequence, with duplicates removed.
/// - Note: Has equivalent elements to `Set(self)`.
@available(
swift, deprecated: 5.4,
message: "Doesn't compile without the constant in Swift 5.3."
)
var firstUniqueElements: [Element] {
let getSelf: (Element) -> Element = \.self
return firstUniqueElements(getSelf)
}
}
public extension Sequence where Element: Equatable {
/// The elements of the sequence, with duplicates removed.
/// - Note: Has equivalent elements to `Set(self)`.
@available(
swift, deprecated: 5.4,
message: "Doesn't compile without the constant in Swift 5.3."
)
var firstUniqueElements: [Element] {
let getSelf: (Element) -> Element = \.self
return firstUniqueElements(getSelf)
}
}
public extension Sequence {
/// The elements of the sequences, with "duplicates" removed
/// based on a closure.
func firstUniqueElements<Hashable: Swift.Hashable>(
_ getHashable: (Element) -> Hashable
) -> [Element] {
var set: Set<Hashable> = []
return filter { set.insert(getHashable($0)).inserted }
}
/// The elements of the sequence, with "duplicates" removed,
/// based on a closure.
func firstUniqueElements<Equatable: Swift.Equatable>(
_ getEquatable: (Element) -> Equatable
) -> [Element] {
reduce(into: []) { uniqueElements, element in
if zip(
uniqueElements.lazy.map(getEquatable),
AnyIterator { [equatable = getEquatable(element)] in equatable }
).allSatisfy(!=) {
uniqueElements.append(element)
}
}
}
}
如果顺序不重要,那么你总是可以使用这个Set初始化式。