如何从数组中删除重复项
如何从一个数组中删除重复项
有时候我们需要从一个数组中删除重复的元素。我们可以使用数组函数contains(_: )来检查一个元素是否已经存在于数组中,但是这种方法对于大型数组来说效率并不高。更好的方法是将数组的元素复制到一个Set集合中,然后使用Set集合的操作来查找和删除重复项。Set集合经过优化,测试集合成员的速度很快,所以if aSet.contains(item)的速度比if anArray.contains(item)要快得多。
如果您不在意保留项目的顺序,您可以简单地将数组复制到一个集合中,然后再复制回一个数组。然而,这意味着结果数组中的项目将以不同的顺序排列。
下面是一个保留顺序的数组中删除重复字符串的函数的示例:
func uniqueElementsFrom(array: [String]) -> [String] {
//创建一个空的Set来跟踪独特的项
var set = Set
let result = array.filter {
guard !set.contains($0) else {
//如果Set已经包含这个对象,则返回false,跳过它
return false
}
//将这个项添加到Set中,因为它现在将在数组中
set.insert($0)
//返回true,以使过滤后的数组包含这个项
return true
}
return result
}
如果您像这样调用它:
let arrayOfStrings = ["a", "b", "a", "c", "a", "d"]
let uniqueStrings = uniqueElementsFrom(array:arrayOfStrings)
print("Unique elements from \(arrayOfStrings) = \n” +
“\(uniqueStrings)")
输出将会是:
Unique elements from ["a", "b", "a", "c", "a", "d"] = [“a”, "b", "c", "d"]
然而,这个函数只适用于字符串数组。如果我们能够编写一个能够从任何类型的数组中删除重复项的函数就好了。
这就是泛型的作用。然而,有一个注意事项。集合只能包含符合Hashable协议的对象,因为集合使用散列来加快测试集合成员的速度。
我们可以使用泛型重写uniqueElementsFrom(array:)函数,使其接受符合Hashable协议的任何数组。代码如下:
func uniqueElementsFrom
var set = Set
let result = array.filter {
guard !set.contains($0) else {
return false
}
set.insert($0)
return true
}
return result
}
函数名后面的
这种形式的uniqueElementsFrom(array:)函数适用于任何元素都符合Hashable协议的数组。
(1.) 对于数组而言,contains(_: )的性能为O(n),所以通过循环遍历数组,并使用contains(_: )测试数组是否包含每个新元素的性能几乎为O(n^2),这对于除了小型数组之外的任何情况来说都非常糟糕。我相信Set的contains(_: )函数具有常数时间性能,所以整个过程的性能应该为O(n)。
(评论中的一些问题和回答略)