2016-10-06 4 views
1

Ich fragte eine ähnliche Frage vor einer Weile. Es war die Frage, wie kann ich ein Array wie folgt drehen:Wie man ein Array * auf diese Weise * schnell flacht?

[[1,2,3],[4,5,6],[7,8,9]] 

dazu:

[1,2,3,4,5,6,7,8,9] 

Aber jetzt will ich das gleiche Array diese aktivieren:

[1,4,7,2,5,8,3,6,9] 

alle Angenommen Die Subarrays haben die gleiche Länge.

Wenn Sie es nicht bereits bemerkt haben, sind die ersten drei Elemente im Ergebnis das erste Element der drei Unterfelder. Das vierte, fünfte und sechste Element im Ergebnis ist das zweite Element jedes Unterfelds.

Wenn Sie nicht noch verstehen, vielleicht wird dies dazu beitragen:

Original-Array:

Ergebnis:

[ 
    1,4,7, 
    2,5,8, 
    3,6,9 
] 

Im Moment habe ich dies:

func flatten(array: [[Int]]) -> [Int] { 
    var flat = [Int]() 
    for i in 0..<array[0].count { 
     for subarray in array { 
      flat.append(subarray[i]) 
     } 
    } 
    return flat 
} 

Ich nicht denke das ist sehr swfity. Wie kann ich das auf eine schnelle Art und Weise machen?

Um zu vermeiden, ein XY-Problem zu sein, hier ist, warum ich dies tun möchte.

Ich entwickle ein Brettspiel. Ich benutze HLGridNode (Es ist im Grunde eine Reihe von Quadraten in einem gitterartigen Layout) von HLSpriteKit als Brettspielbrett. Um den Inhalt des Gitterknotens zu bearbeiten, muss ich ein 1D-Array von Sprite-Knoten übergeben, kein 2D-Array.

Um mein Leben zu erleichtern, habe ich die Modellobjekte in einem 2D-Array gespeichert. Auf diese Weise kann I in die sqaure 5 Quadrate von den linken und 2 Felder von oben beziehen nur indem:

modelObjects[5][2] 

Wenn ich das Array 2D abzuflachen .flatMap { $0 } verwendet und das Ergebnis an den Gitterknoten passieren, modelObjects[5][2] würde erscheinen 2 Quadrate von links und 5 Quadrate von oben.

Dies ist kein Duplikat von this, da diese Frage eine bestimmte Anzahl von Arrays zu haben scheint. Obwohl ich mein 2D-Array in eine Schleife stecken kann und diese Sachen mache, scheint es ein wirklich langatmiger Ansatz zu sein. Ich denke, es muss einfacher sein, dies mit 2D-Arrays zu tun.

+4

Mögliches Duplikat von [Kombination mehrerer Arrays zu einem, nacheinander fortlaufend] (http://stackoverflow.com/questions/39696381/combining-multiple-arrays-into-one-indexing-sequentiell) – Hamish

+0

"Ich entwickle ein Brettspiel. " Das ist das Problem, das Sie versuchen zu lösen. Sie haben das Array-Problem bereits gelöst. Jede weitere Zeit ist eine Ablenkung von Ihrem eigentlichen Ziel. Das heißt nicht, dass das Problem nicht interessant ist. Es ist einfach nicht wichtig zu lösen. –

+1

Zu Ihrer Bearbeitung: Von einem kurzen Blick auf den "Duplikat-Kandidaten" scheint es mir, dass es Antworten hat, die * nicht * eine bestimmte Anzahl von Arrays annehmen, mit denen zu arbeiten. –

Antwort

2

Hier ist eine Verbesserung gegenüber Shadow Of ‚s answer:

func transpose<T>(matrix: [[T]]) -> [[T]] { 
    guard !matrix.isEmpty else { return matrix } 
    return matrix[0].indices.map{ index in 
     matrix.map{ $0[index] } 
    } 
} 
+0

Mehr swifty =) –

+1

Es ist nicht Swifty, bis es in einer Extension ist;) – Alexander

+0

Wenn ich versuchte, Erweiterung zu schreiben, werde ich verrückt. Versucht, 'map' zu verwenden, führte zu" segmentation fault "ohne sichtbaren Grund, versucht,' indicies' zu verwenden, was zu nervigen "unable indices" führte. Endlich bekomme ich diese funktionierende Version. Ich weiß, wie man es in Swift 2 schreibt, aber hier in Swift 3 sieht es so hässlich aus. Kannst du mir meine aktualisierte Antwort ansehen und vielleicht auf einige Fehler hinweisen oder Wege, es einfacher zu machen? –

1

Sie können Ergebnis erhalten Sie wollten durch Ihre 2D-Matrix transponieren, indem zum Beispiel diese Funktion:

func matrixTranspose<T>(_ matrix: [[T]]) -> [[T]] { 
    if matrix.isEmpty {return matrix} 
    var result = [[T]]() 
    for index in 0..<matrix.first!.count { 
     result.append(matrix.map{$0[index]}) 
    } 
    return result 
} 

und flatten (joined in swift 3) dann anwenden.

let arr = [[1,2,3],[4,5,6],[7,8,9]] 
print(matrixTranspose(arr)) 
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 

print(matrixTranspose(arr).flatMap{$0}) 
// [1, 4, 7, 2, 5, 8, 3, 6, 9] 

Erweiterung Version:

extension Collection where Self.Iterator.Element: Collection { 
    var transpose: Array<Array<Self.Iterator.Element.Iterator.Element>> { 
     var result = Array<Array<Self.Iterator.Element.Iterator.Element>>() 
     if self.isEmpty {return result} 

     var index = self.first!.startIndex 
     while index != self.first!.endIndex { 
      var subresult = Array<Self.Iterator.Element.Iterator.Element>() 
      for subarray in self { 
       subresult.append(subarray[index]) 
      } 
      result.append(subresult) 
      index = self.first!.index(after: index) 
     } 
     return result 
    } 
} 

mit Nutzung

let arr = [[1,2,3],[4,5,6],[7,8,9]] 
print(arr.transpose) 
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]] 
+0

Versuchen Sie, '0 .. Alexander

+2

Wenn Sie die Erweiterung für 'Array' vornehmen, sollten Sie nur die Einschränkung' Element.Indices.Iterator.Element == Element.Index' hinzufügen können (siehe [diese Q & A] (http://stackoverflow.com/questions/39179660/swift-2d-array-generische-Erweiterung-Problem-Zugriff-2nd-Dimension)) und verwenden Sie einfach @ AlexanderMomchliov-Implementierung für die Erweiterung (ersetzen Sie "Matrix" durch "Selbst"). – Hamish

Verwandte Themen