具有等式元素的数组的 Swift 扩展无法调用索引(的 :)

use*_*320 1 arrays swift swift-extensions

我试图在 Swift 中为 Array 类型添加一个扩展,仅限于其元素符合 equatable 协议的数组。我试图以下列方式定义一个函数:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

该函数的目的是返回原始数组中没有出现在newArray.

我在 Xcode 中收到的错误是:无法使用类型为 '(of: Element)' 的参数列表调用 'index'

因为我只为元素可相等的数组定义函数,并且要求 的元素是newArray可相等的,所以我不确定为什么我不能调用索引方法。

Ham*_*ish 5

问题是你T在你的方法中定义了一个新的通用占位符——它不一定与Element. 因此,当您说 时newArray.index(of: element),您是在尝试将 an 传递Element给 type 的参数T

因此,解决方案是简单地将newArray:参数键入为[Element]

extension Array where Element : Equatable {
    func deletedIndicies(byKeeping elementsToKeep: [Element]) -> [Int] {
        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

作为旁注,此方法也可以实现为:

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

此外,如果您将约束更改ElementHashable,这也可以在 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)