我正在尝试将以下函数转换为2D数组的通用扩展。
func rotate(_ input: [[Int]]) -> [[Int]]
{
let length = input[0].count
var value = Array(repeating: [Int](), count: length)
for index in 0 ..< length
{
value[index] = input.map { $0[index] }.reversed()
}
return value
}
我特别难以指出如何指定约束以允许我访问第二个维度。这是一次失败的尝试:
extension Array where Element: Collection, Element.Iterator.Element: Collection
{
private func rotate()
{
let count = self[0].count // Element.IndexDistance instead of Int
// Expression type 'Array<Element>' is ambiguous without more context
var returnValue = Array(repeating: Element, count: 11)
for index in 0 ..< count // Element.IndexDistance instead of Int
{
returnValue[index] = self.map { $0[index] }.reversed()
}
return returnValue
}
}
答案 0 :(得分:3)
问题在于,编译器并不知道您的扩展是针对2D数组的 - 它只知道它对于集合数组而言。因此,相关类型IndexDistance
和Index
不一定是Int
。
因此,解决方案是限制您的扩展程序,以使Element
的{{1}} IndexDistance
和Index
类型为Int
。这将允许您形成范围0..<count
,因为count
现在将是Int
(IndexDistance
)类型 - 您将能够下标{{1}内的元素1}} map(_:)
s(因为下标需要Int
)。
(支持concrete same-type requirements后执行此操作非常简单,因为您可以简单地将Index
约束为Element
,但这还不可能。)功能
您还应该注意,您的约束Array
是不正确的,因为它会将扩展约束到集合的3D数组(元素是集合的数组,其中该集合的元素是集合)。
最后,您可能需要定义一个Element.Iterator.Element: Collection
来代表内部元素&#39; 2D数组的类型,因为Swift目前有some limitations when working with nested types directly,例如在创建该类型的空2D数组时。
因此,您当前方法的工作版本如下所示:
typealias
使用嵌套extension Array where Element: Collection, Element.Index == Int, Element.IndexDistance == Int {
private func rotate() -> [[Element.Iterator.Element]] {
typealias InnerElement = Element.Iterator.Element
// in the case of an empty array, simply return an empty array
if self.isEmpty { return [] }
let length = self[0].count
var returnValue = [[InnerElement]](repeating: [InnerElement](), count: length)
for index in 0..<length {
returnValue[index] = self.map{ $0[index] }.reversed()
}
return returnValue
}
}
可以大大简化@MartinR points out below,因为我们不再需要创建&#39;结果&#,因此无需map(_:)
39;阵列:
typealias
虽然请注意,您的扩展程序限制仅适用于private func rotate() -> [[Element.Iterator.Element]] {
if self.isEmpty { return [] }
let length = self[0].count
return (0..<length).map { index in
self.map { $0[index] }.reversed()
}
}
索引并非严格必要(但不会产生任何实际差异,因为您只打算将其用于2D数组)。另一种方法是直接遍历内部集合Int
。
为了做到这一点,您只需要约束您的扩展程序,以便内部集合indices
具有与Indices
相同类型的Element
集合(如果是Index
,Array
是Indices
):
CountableRange<Int>