2016-06-02 1 views
30

So habe ich eine for-Schleife, die in etwa so aussieht:Wie schreibe ich eine For-Schleife in Swift 3 für ein Array, das ich während der for-Schleife ändere?

for var i = 0; i < results.count ; i += 1 { 
    if (results[i] < 5) { 
     results.removeAtIndex(i) 
     i -= 1 
    } 
} 

Dies ist früher zu arbeiten. Aber wenn ich es auf die bevorzugte Swift 3.0 Syntax geändert:

for var i in 0..<results.count { 
    if (results[i] < 5) { 
     results.removeAtIndex(i) 
     i -= 1 
    } 
} 

ich eine Array IOOBE Ausnahme erhalten, weil es nicht die Zählung erneut überprüfen und weiter auf, bis die ursprünglichen results.count.

Wie behebe ich das? Es funktioniert jetzt, aber ich will in Zukunft nicht in Schwierigkeiten geraten.

+0

dieser Code nicht für var beschwert sich in i 0 ..

+0

es macht keinen Sinn, warum Apple die for-Schleife so komplex machte, ich erinnere mich nie daran, ein Problem mit ihm für die letzten 25 Jahre –

Antwort

50

Während die Lösung Gebrauch macht von filter eine feine Lösung ist, und es ist mehr Swift-ly gibt es eine andere Art und Weise, wenn die Verwendung von for-in machen, ist dennoch nach wie vor erwünscht:

var results = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

for var i in (0..<results.count).reverse() 
{ 
    if (results[i] < 5) 
    { 
     results.removeAtIndex(i) 
     //i -= 1 
    } 
} 

print(results) 

Ergebnis:

[5, 6, 7, 8, 9, 10] 

Wir konnten diese Zeile weglassen i -= 1 zusammen, zusätzlich.

Das Problem mit removeAtIndex innerhalb der Schleife ist, dass es nicht das Array selbst in-place und damit neu indizieren verursachen aufgrund count eine Anordnung außerhalb der Grenzen Ausnahme verursachte, nicht aktualisiert werden.

Durch die Rückwärtsbewegung kann die Ausnahme außerhalb der Grenzen vermieden werden.

+1

Oh Gott ... das ist wirklich schlau.Ja, ich weiß, dass der Filterweg * schneller * sein würde, aber ich denke, dass dieser Weg besser ist, ich werde ihn benutzen. Vielen Dank! – QuantumHoneybees

+0

Hurra, ein Editor eines OP, das tatsächlich eine gut erhaltene Antwort bietet, nicht nur Bearbeitung, um rep zu erhöhen. Selten. – aremvee

+0

@Unheiling - .reverse() Diese Funktion wird in swift3 nicht unterstützt. Kann jemand mehr zur selben Frage beitragen? –

14

Können Sie stattdessen eine filter verwenden?

let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 
let greaterThan5 = numbers.filter{$0 >= 5} 
print(greaterThan5) 
+0

Ah, du hast Recht! Ich werde modifizieren, danke! –

+0

Das neue Array sollte den Namen 'greaterThan4' haben;) Dies ist jedoch der richtige Weg, um das Problem zu lösen. –

+0

Oh ja richtig! Die Funktion, die dies aufruft, heißt "filterArray". Ich habe nie die Verbindung hergestellt, haha. Aber ich brauche auch die gefilterten Ergebnisse, die an das Ende angehängt werden. Irgendwelche Vorschläge? – QuantumHoneybees

10

Wenn Sie eine for -loop weiterhin verwenden möchten, können Sie beide aufzählen über Index und Element mit enumerate:

for (index, element) in results.enumerate() { 
    if (element < 5) { 
    results.removeAtIndex(index) 
    } 
} 

Obwohl je nachdem, was Sie in Ihrer Schleife tun, die filter Methode könnte eine bessere Idee sein.

+7

Das ist eine schlechte Idee, Sie werden unter bestimmten Umständen in die Out-of-Range-Falle geraten, versuchen Sie zum Beispiel das Array '[6, 5, 4, 3, 2, 1]'. Der Grund ist, dass das Array in der Schleife geändert wird, aber der Index nicht angepasst wird. – vadian

0

Wenn Ihre Schleife vorwärts geht ...

for var i in (0..<results.count) where results.indices.contains(i) { 

//if the index doesn't exist, the loop will be stopped. 

if (results[i] < 5) { 
     results.removeAtIndex(i) 
    } 

}