我可能有一个像下面这样的数组:
[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是否提供了一种容易做到这一点的方法,还是我必须自己做?
当前回答
Xcode 10.1 - Swift 4.2简单而强大的解决方案
func removeDuplicates(_ nums: inout [Int]) -> Int {
nums = Set(nums).sorted()
return nums.count
}
例子
var arr = [1,1,2,2,3,3,4,4,5,5,6,6,7,7,8,8,9,9]
removeDuplicates(&arr)
print(arr) // [1,2,3,4,5,6,7,8,9]
其他回答
另一种(如果不是最优的)解决方案是使用不可变类型而不是变量:
func deleteDuplicates<S: ExtensibleCollectionType where S.Generator.Element: Equatable>(seq:S)-> S {
let s = reduce(seq, S()){
ac, x in contains(ac,x) ? ac : ac + [x]
}
return s
}
包括对比Jean-Pillippe的命令式方法和函数式方法。
作为奖励,这个函数不仅可以处理数组,还可以处理字符串!
编辑:这个答案是在2014年为Swift 1.0编写的(在Set在Swift中可用之前)。它不需要Hashable一致性,并且在二次时间内运行。
如果你想保持秩序,那么就用这个
let fruits = ["apple", "pear", "pear", "banana", "apple"]
let orderedNoDuplicates = Array(NSOrderedSet(array: fruits).map({ $0 as! String }))
斯威夫特2
用uniq函数回答:
func uniq<S: SequenceType, E: Hashable where E==S.Generator.Element>(source: S) -> [E] {
var seen: [E:Bool] = [:]
return source.filter({ (v) -> Bool in
return seen.updateValue(true, forKey: v) == nil
})
}
use:
var test = [1,2,3,4,5,6,7,8,9,9,9,9,9,9]
print(uniq(test)) //1,2,3,4,5,6,7,8,9
我的解决方案,它似乎可以在O(n)时间,因为哈希映射访问是O(1),过滤器是O(n)。它还使用by闭包来选择按顺序区分元素的属性。
extension Sequence {
func distinct<T: Hashable>(by: (Element) -> T) -> [Element] {
var seen: [T: Bool] = [:]
return self.filter { seen.updateValue(true, forKey: by($0)) == nil }
}
}
让我提出一个类似于斯科特·加德纳的答案,但使用了更简洁的reduce语法。 此解决方案从自定义对象数组中删除重复项(保持初始顺序)
// Custom Struct. Can be also class.
// Need to be `equitable` in order to use `contains` method below
struct CustomStruct : Equatable {
let name: String
let lastName : String
}
// conform to Equatable protocol. feel free to change the logic of "equality"
func ==(lhs: CustomStruct, rhs: CustomStruct) -> Bool {
return (lhs.name == rhs.name && lhs.lastName == rhs.lastName)
}
let categories = [CustomStruct(name: "name1", lastName: "lastName1"),
CustomStruct(name: "name2", lastName: "lastName1"),
CustomStruct(name: "name1", lastName: "lastName1")]
print(categories.count) // prints 3
// remove duplicates (and keep initial order of elements)
let uniq1 : [CustomStruct] = categories.reduce([]) { $0.contains($1) ? $0 : $0 + [$1] }
print(uniq1.count) // prints 2 - third element has removed
如果你想知道这个约简魔法是如何工作的,这里是完全相同的,只是使用了更扩展的约简语法
let uniq2 : [CustomStruct] = categories.reduce([]) { (result, category) in
var newResult = result
if (newResult.contains(category)) {}
else {
newResult.append(category)
}
return newResult
}
uniq2.count // prints 2 - third element has removed
你可以简单地复制粘贴这段代码到Swift Playground中。