map(keyPath) 其中 keyPath 是一个变量

Rom*_*man 3 swift keypaths swift5

let arr = [(1, 1), (2, 2), (3, 3), (4, 4), (5, 5)]
arr.map(\.0) // [1, 2, 3, 4, 5]
Run Code Online (Sandbox Code Playgroud)

效果很好。但下面的代码无法编译:

let keyPath = \(Int, Int).0
arr.map(keyPath)
Run Code Online (Sandbox Code Playgroud)

无法将类型“WritableKeyPath<(Int, Int), Int>”的值转换为预期参数类型“((Int, Int)) throws -> T”。
无法推断通用参数“T”。

New*_*Dev 5

Array.map期望带有签名的闭包(Element) throws -> T

在 Swift 5.2 中,允许关键路径作为函数/闭包传递(这是一个演化提案),但只能作为文字传递(至少,根据该提案,它说“现在”,所以也许这个限制会被取消) )。

Sequence为了克服这个问题,您可以创建一个接受关键路径的扩展:

extension Sequence {
   func map<T>(_ keyPath: KeyPath<Element, T>) -> [T] {
      return map { $0[keyPath: keyPath] }
   }
}
Run Code Online (Sandbox Code Playgroud)

(来源:https ://www.swiftbysundell.com/articles/the-power-of-key-paths-in-swift/ )

然后你可以做你想做的事:

let keyPath = \(Int, Int).0
arr.map(keyPath)
Run Code Online (Sandbox Code Playgroud)

  • 同样根据相同的演化建议,您可以编写“let transform: ((Int, Int)) -&gt; Int = \.0”,然后编写“arr.map(transform)”。 (2认同)