2017-06-26 3 views
1

Ich versuche, Array<MutatingCollection> zu erweitern, damit ich den Inhalt eines Arrays von Arrays spiegeln kann, aber der Compiler sagt, ich kann reverse() nicht auf den Elementen in aufrufen Array, obwohl reverse() in MutatingCollection Protokoll definiert ist.Schnelle Erweiterung von Array <MutableCollection> erlaubt keine Umkehrung()

möchte ich so etwas wie dies zu tun:

var table = [[0,1,2], 
      [3,4,5], 
      [6,7,8]] 
table.mirror() 
//table now [[2,1,0], 
//   [5,4,3], 
//   [8,7,6]] 

Hier ist meine (nicht funktioniert) Code:

extension Array where Element == MutableCollection { 
     mutating func mirror() { 
      for index in self.indices { 
       self[index].reverse() 
      } 
     } 
    } 

ich es als self.map {array in array.reverse()} auch versucht haben (was ich denken tut das gleiche, aber ich bin nicht völlig grok map()) Beide Möglichkeiten führen zu der gleichen Fehlermeldung:

Member 'reverse' cannot be used on value of type 'MutableCollection'

Edit: Ich kann den gleichen Code direkt aufrufen und es funktioniert, wie ich es vorhatte.

Playgrounds Screenshot

Vielleicht verwende ich extension unsachgemäß oder Swift Spielplätze meinen Zugang irgendwie blockiert.

Antwort

1

Zunächst einmal sollte die Erweiterung wie folgt erklärt werden:

extension Array where Element : MutableCollection { 

Sie wollen prüfen, ob Element das Protokoll haftet MutableCollection, nicht, dass es ein MutableCollection

jedoch ist, dann ich Ich bin nicht in der Lage, die reverse Methode auf dem subscript aus irgendeinem Grund anzurufen. Das Beste, was ich habe in der Lage zu tun, ist dies:

extension Array where Element : MutableCollection { 
    mutating func mirror() { 
    for index in self.indices { 
     self[index] = self[index].reversed() as! Element 
    } 
    } 
} 

Welche funktioniert, wie Sie es arbeiten müssen, obwohl die gezwungene Guss sehr hässlich ist, und ich mag nicht, es zu tun. Ich nehme an, ich sollte die Besetzung testen, um sicher zu sein, aber ich kann keinen Fall sehen, bei dem das Aufrufen von reversed() zu einer Sammlung führen würde, die nicht in Element umgewandelt werden konnte.

Edit:

dachte ich, das Problem aus. Die reverse() Methode ist nur gültig auf MutableCollection, wenn es auch eine BidirectionalCollection ist. Dieser Code funktioniert jetzt korrekt:

extension MutableCollection where 
    Iterator.Element : MutableCollection & 
        BidirectionalCollection, 
    Indices.Iterator.Element == Index { 
    mutating func mirror() { 
    for index in self.indices { 
     self[index].reverse() 
    } 
    } 
} 

Nun sollte der Code für alle MutableCollection deren Elemente arbeiten, sind sowohl ein MutableCollection und BidirectionalCollection - wie [Array<Int>] oder sogar [ArraySlice<Int>]

Sie können den vollständigen Code für reverse() in Swift sehen 3.hier 1:

Reverse.swift

Erweiterung MutableCollection wo Self: BidirectionalCollection

+0

Dieser stürzt ab, wenn 'Element' ein veränderliches Sammlung ist aber kein Array, z.B. für 'var table = [[0,1,2] .dropFirst(), [3,4,5], [6,7,8]]', wobei 'Element'' ArraySlice 'ist. –

+0

@MartinR Ich glaube, ich habe die Ursache für das Problem in dieser Frage genagelt, sowie Korrektur für das Problem, das Sie erwähnt haben. Bitte zögern Sie nicht, ihre Richtigkeit für mich zu überprüfen. – ColGraff

+1

Mit einer zusätzlichen Einschränkung 'Indices.Iterator.Element == Index' können Sie den künstlichen 'guard let index = index ...' loswerden, vergleichen https://stackoverflow.com/a/44457590/1187415 oder https: //stackoverflow.com/a/40331858/1187415. Es sollte nicht in Swift 4 notwendig sein. –