我试图在Swift中为Array类型添加一个扩展,仅限于其元素符合equatable协议的Arrays。我试图以下列方式定义一个函数:
import Foundation
extension Array where Iterator.Element: Equatable {
func deletedIndicies<T: Equatable>(newArray: [T]) -> [Int] {
var indicies = [Int]()
for element in self {
if newArray.index(of: element) == nil {
indicies.append(self.index(of: element)!)
}
}
return indicies
}
}
}
该函数的目的是返回原始数组中未出现在newArray
中的任何项的索引。
我在Xcode中收到的错误是:无法调用&#39; index&#39;使用类型&#39;(of:元素)&#39;
的参数列表由于我只为那些元素是等同的Arrays定义函数,并且要求newArray
的元素是等价的,所以我不确定为什么我不能调用索引方法。
答案 0 :(得分:4)
问题是您在方法中定义了一个新的通用占位符T
- 其类型不一定与Element
相同。因此,当您说newArray.index(of: element)
时,您尝试将Element
传递给T
类型的参数。
因此,解决方案是只需将newArray:
参数键入[Element]
:
extension Array where Element : Equatable {
func deletedIndicies(byKeeping elementsToKeep: [Element]) -> [Int] {
// ...
}
}
作为旁注,这种方法也可以实现为:
extension Array where Element : Equatable {
func deletedIndicies(byKeeping elementsToKeep: [Element]) -> [Int] {
// use flatMap(_:) to iterate over a sequence of pairs of elements with indices,
// returning the index of the element, if elementsToKeep doesn't contains it,
// or nil otherwise, in which case flatMap(_:) will filter it out.
return self.enumerated().flatMap {
elementsToKeep.contains($1) ? nil : $0
}
}
}
此外,如果您将Element
上的约束更改为Hashable
,这也可以在O(n)中实现,而不是O(n * m)时间,这可能是可取的:
extension Array where Element : Hashable {
func deletedIndicies(byKeeping elementsToKeep: [Element]) -> [Int] {
// create new set of elements to keep.
let setOfElementsToKeep = Set(elementsToKeep)
return self.enumerated().flatMap {
setOfElementsToKeep.contains($1) ? nil : $0
}
}
}