说我有一个字符串数组:
let arrayOfStrings = ["a", "b", "a", "c", "a", "d"]
我如何摆脱重复?
答案 0 :(得分:14)
您可以使用数组函数contains(_:)
来检查元素是否已经是数组的一部分,但这相当慢,而对于大型数组,它将无法正常运行。 (1。)最好将条目复制到Set
并使用Set
操作来查找和删除重复项。集合经过优化,可以快速测试集合成员资格,因此if aSet.contains(item)
比if anArray.contains(item)
快得多。
如果您不关心保留项目的顺序,只需将数组复制到一个集合中,然后再复制到数组中即可。但是,这确实意味着结果数组中的项目将采用不同的顺序。
在保留顺序的同时从字符串数组中删除重复项的函数可能如下所示:
func uniqueElementsFrom(array: [String]) -> [String] {
//Create an empty Set to track unique items
var set = Set<String>()
let result = array.filter {
guard !set.contains($0) else {
//If the set already contains this object, return false
//so we skip it
return false
}
//Add this item to the set since it will now be in the array
set.insert($0)
//Return true so that filtered array will contain this item.
return true
}
return result
}
如果您使用以下代码调用它:
let arrayOfStrings = ["a", "b", "a", "c", "a", "d"]
let uniqueStrings = uniqueElementsFrom(array:arrayOfStrings)
print("Unique elements from \(arrayOfStrings) = \n” +
“\(uniqueStrings)")
输出为
来自[“a”,“b”,“a”,“c”,“a”,“d”的独特元素] =
[“a”,“b”,“c”,“d”]
但是,该函数仅适用于字符串数组。如果我们能编写一个可以从任何类型的数组中删除重复的函数,那将是件好事。
这是Generics的工作。但是有一个问题。集合只能包含符合Hashable
协议的对象,因为集合使用哈希来更快地测试集合成员资格。
我们可以使用Generics重写uniqueElementsFrom(array:)
函数以获取符合Hashable
协议的任何数组。该代码如下所示:
func uniqueElementsFrom<T: Hashable>(array: [T]) -> [T] {
var set = Set<T>()
let result = array.filter {
guard !set.contains($0) else {
return false
}
set.insert($0)
return true
}
return result
}
函数名称后面的<T: Hashable>
位表示“此函数的其余部分将引用未指定的类型T。唯一可以确定的是类型T将符合Hashable协议。“
这种形式的uniqueElementsFrom(array:)
函数适用于任何元素为Hashable
的数组。
(1。)对于数组,contains(_:)
具有O(n)
性能,因此循环遍历数组,测试数组以查看它是否包含{{ {1}}的性能差不多是contains(_:)
,除了小数组之外,其他任何东西都非常非常。我很确定O(n^2)
的{{1}}函数具有恒定的时间性能,因此整个过程将具有Set
性能。