Das Problem ist, dass der Compiler nicht weiß, dass Ihre Erweiterung für 2D-Arrays ist - er weiß nur, dass es für Arrays von Sammlungen ist. Daher sind die zugehörigen Typen IndexDistance
und Index
nicht notwendigerweise Int
.
Die Lösung ist daher Ihre Erweiterung zu beschränken, so dass die Element
‚s IndexDistance
und Index
vom Typ sind Int
. Auf diese Weise können Sie den Bereich bilden 0..<count
, wie count
jetzt vom Typ sein Int
(IndexDistance
) - und Sie werden die Elemente innerhalb der map(_:)
mit Int
s zu SUBSCRIPT fähig sein (als der Index eine Index
erwartet).
(Dies wird trivial sein, wenn concrete same-type requirements tun werden unterstützt, wie Sie einfach die Element
einschränken könnte ein Array
, dies ist jedoch noch nicht möglich. Sein)
Sie sollten auch, dass Ihre Constraint Element.Iterator.Element: Collection
beachten ist falsch, da dies die Erweiterung auf 3D-Arrays von Sammlungen einschränkt (Ein Array, in dem das Element eine Sammlung ist, wobei die Elemente dieser Sammlung eine Sammlung sind).
Schließlich kann man ein typealias
zu repräsentieren den ‚inneres Element‘ Typen des 2D-Arrays definieren müssen, da derzeit Swift some limitations when working with nested types directly hat, zum Beispiel wenn eine leeren 2D-Arrays dieses Typs zu schaffen.
Daher ist eine funktionierende Version der aktuellen Methode würde wie folgt aussehen:
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
}
}
die, wie @MartinR points out below, erheblich vereinfacht eine verschachtelte map(_:)
unter Verwendung, wodurch die Notwendigkeit eines typealias
wie wir nicht sein könnten länger brauchen ein 'Ergebnis' Array zu erstellen:
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()
}
}
Obwohl zu beachten, dass der Einschränkungs von y unsere Erweiterung, nur mit Int
Indizes zu arbeiten, ist nicht unbedingt notwendig (macht aber keinen praktischen Unterschied, da Sie nur mit 2D-Arrays arbeiten möchten). Eine andere Alternative besteht darin, direkt über die indices
der inneren Sammlung zu iterieren.
Um dies zu tun, geben Sie einfach Ihre Erweiterung beschränken müssen, so dass die Indices
innere Sammlung Element
s von der gleichen Art wie die Index
der Sammlung haben (im Falle eines Array
ist Indices
ein CountableRange<Int>
):
extension Array where Element: Collection, Element.Indices.Iterator.Element == Element.Index {
private func rotate() -> [[Element.Iterator.Element]] {
if self.isEmpty { return [] }
return self[0].indices.map { index in
self.map { $0[index] }.reversed()
}
}
}
Brilliant + Vielen Dank für die wertvolle Erklärung. – AfricanSwift
Sie können das vereinfachen, um (0 ..
Danke Martin ... – AfricanSwift