Gibt es eine Möglichkeit, in Swift mit umgekehrten Bereichen zu arbeiten?
Beispielsweise:
for i in 5...1 {
// do something
}
ist eine Endlosschleife.
In neueren Versionen von Swift wird dieser Code kompiliert, aber zur Laufzeit wird der Fehler ausgegeben:
Schwerwiegender Fehler: Bereich kann nicht mit UpperBound <LowerBound gebildet werden
Ich weiß, dass ich 1..5
stattdessen verwenden, berechnen j = 6 - i
und j
als meinen Index verwenden kann. Ich habe mich nur gefragt, ob es etwas Lesbareres gibt.
Antworten:
Update Für das neueste Swift 3 (funktioniert immer noch in Swift 4)
Sie können die
reversed()
Methode für einen Bereich verwendenOder
stride(from:through:by:)
Methodestide(from:to:by:)
ist ähnlich, schließt jedoch den letzten Wert ausUpdate Für den neuesten Swift 2
Zunächst ändern Protokollerweiterungen die
reverse
Verwendung:for i in (1...5).reverse() { print(i) } // 5 4 3 2 1
Stride wurde in Xcode 7 Beta 6 überarbeitet. Die neue Verwendung lautet:
Es funktioniert auch für
Doubles
:Seien Sie vorsichtig bei Gleitkomma-Vergleichen hier für die Grenzen.
Frühere Bearbeitung für Swift 1.2 : Ab Xcode 6 Beta 4 existieren by und ReverseRange nicht mehr: [
Wenn Sie nur einen Bereich umkehren möchten, benötigen Sie lediglich die Umkehrfunktion:
Wie gepostet 0x7fffffff gibt es ein neues Stride - Konstrukt , das zu wiederholen und Schritt durch beliebige ganze Zahlen verwendet werden kann. Apple gab auch an, dass Gleitkomma-Unterstützung kommt.
Aus seiner Antwort entnommen:
quelle
(1...5).reverse()
(als Funktionsaufruf), bitte aktualisieren Sie Ihre Antwort. (Da es nur zwei Zeichen sind, konnte ich Ihren Beitrag nicht bearbeiten.)(1...5).reversed()
. Außerdem.stride()
funktioniert das Beispiel für nicht und benötigtstride(from:to:by:)
stattdessen die freie Funktion .stride
Code für Swift 3 etwas falsch ist.through
to
for i in stride(from:5,through:1,by:-1) { print(i) }
reversed
O (1) eine Komplexität aufweist, da es lediglich die ursprüngliche Sammlung umschließt und keine Iteration erfordert, um sie zu erstellen.Die Asymmetrie hat etwas Beunruhigendes:
... im Gegensatz dazu:
Das bedeutet, dass ich jedes Mal, wenn ich einen umgekehrten Bereich machen möchte, daran denken muss, die Klammern zu setzen, und dass ich das
.reverse()
am Ende schreiben muss, das wie ein schmerzender Daumen hervorsteht. Dies ist wirklich hässlich im Vergleich zum C-Stil für Schleifen, die symmetrisch hoch- und runterzählen. Daher habe ich stattdessen C-Style für Loops verwendet. Aber in Swift 2.2 verschwinden die C-Style-for-Loops! Also musste ich herumhasten, um all meinen dekrementierenden C-Stil für Schleifen durch dieses hässliche.reverse()
Konstrukt zu ersetzen - und mich die ganze Zeit fragen, warum um alles in der Welt gibt es keinen Reverse-Range-Operator?Aber warte! Das ist Swift - wir dürfen unsere eigenen Operatoren definieren !! Auf geht's:
Jetzt darf ich also sagen:
Dies deckt nur den häufigsten Fall ab, der in meinem Code auftritt, aber es ist bei weitem der häufigste Fall, also ist es alles, was ich derzeit brauche.
Ich hatte eine Art interne Krise mit dem Betreiber. Ich hätte es gerne
>..
als Umkehrung verwendet..<
, aber das ist nicht legal: Sie können keinen Punkt nach einem Nicht-Punkt verwenden, wie es scheint. Ich überlegte..>
, entschied aber, dass es zu schwer war, mich davon zu unterscheiden..<
. Das Schöne daran>>>
ist, dass es dich anschreit: " runter zu!" (Natürlich können Sie sich einen anderen Operator einfallen lassen. Aber mein Rat lautet: Definieren Sie<<<
für Supersymmetrie, was zu tun..<
ist, und jetzt haben Sie<<<
und>>>
welche sind symmetrisch und einfach zu tippen.)Swift 3-Version (Xcode 8 Seed 6):
Swift 4-Version (Xcode 9 Beta 3):
Swift 4.2 Version (Xcode 10 Beta 1):
Swift 5-Version (Xcode 10.2.1):
quelle
>>>
Operator ist echt cool! Ich hoffe, dass Swift-Designer auf solche Dinge achten, dennreverse()
es fühlt sich komisch an, am Ende von Ausdrücken in Klammern zu bleiben . Es gibt keinen Grund, warum sie nicht5>..0
automatisch mit Bereichen umgehen könnten , da dasForwardIndexType
Protokoll einen absolut vernünftigendistanceTo()
Operator bietet , mit dem herausgefunden werden kann, ob der Schritt positiv oder negativ sein sollte.Es scheint, dass sich die Antworten auf diese Frage im Laufe der Betas etwas geändert haben. Ab Beta 4 wurden sowohl die
by()
Funktion als auch derReversedRange
Typ aus der Sprache entfernt. Wenn Sie einen umgekehrten Bereich erstellen möchten, haben Sie jetzt folgende Möglichkeiten:1: Erstellen Sie einen Vorwärtsbereich und verwenden Sie die
reverse()
Funktion, um ihn umzukehren.2: Verwenden Sie die neuen
stride()
Funktionen, die in Beta 4 hinzugefügt wurden. Dazu gehören Funktionen zum Angeben des Start- und Endindex sowie des Betrags, um den iteriert werden soll.Beachten Sie, dass ich auch den neuen exklusiven Bereichsoperator in diesen Beitrag aufgenommen habe.
..
wurde ersetzt durch..<
.Bearbeiten: In den Versionshinweisen zu Xcode 6 Beta 5 hat Apple den folgenden Vorschlag hinzugefügt, um damit umzugehen:
Hier ist ein Beispiel.
quelle
lazy(0....5).reverse()
und sehe die Beta 5-Versionshinweise nicht. Kennen Sie andere Diskussionen zu diesem Thema? Außerdem sind die Zahlen in dieserfor
Schleife in Ihrem Beispiel rückwärts.// 0, 1, 2, 3, 4, 5
es im Kommentar, aber es sollte eigentlich umgekehrt werden. Der Kommentar ist irreführend.Xcode 7, Beta 2:
quelle
Swift 3, 4+ : Sie können es so machen:
Ergebnis : 10, 9, 8 ... 0
Sie können es beliebig anpassen. Weitere Informationen finden Sie in der
func sequence<T>
Referenzquelle
Dies könnte ein anderer Weg sein, dies zu tun.
quelle
Die Funktion Reverse () wird für die umgekehrte Nummer verwendet.
Var n: Int // Nummer eingeben
Für i in 1 ... n.reverse () {Print (i)}
quelle