2016-06-02 8 views
30

Tak, mam pętlę do-która wygląda podobnie do tego:Jak napisać pętlę for w Swift 3 dla tablicy, którą modyfikuję podczas pętli for?

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

ten używany do pracy. Ale kiedy zmienił go do składni preferowanego Swift 3.0:

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

uzyskać tablicę IOOBE wyjątek, ponieważ nie ponownie sprawdzić liczbę i kontynuuje aż do oryginalnego results.count.

Jak to naprawić? Działa teraz, ale nie chcę wpaść w kłopoty w przyszłości.

+0

ten kod nie narzeka dla var i in 0 ..

+0

to nie ma sensu, dlaczego jabłko sprawiło, że pętla for była tak skomplikowana, że ​​nigdy nie pamiętam, że miałem z tym problem przez ostatnie 25 lat. –

Odpowiedz

50

Chociaż Wykorzystując rozwiązanie filter jest dobrym rozwiązaniem i to bardziej Swift-ly, nie ma innego sposobu, jeśli wykorzystanie for-in jest, mimo wszystko, nadal pożądane:

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) 

Wynik:

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

Razem możemy pominąć tę linię i -= 1.

Problem removeAtIndex wewnątrz pętli jest to, że nie spowoduje to tablica ponownie indeks sam w miejscu powodującego tablicę poza zakresem wyjątku z powodu count nie jest aktualizowana.

Przechodząc wstecz, można w ten sposób uniknąć wyjątku poza granicami.

+1

O Boże ... to naprawdę sprytne.Tak, wiem, że sposób filtrowania będzie bardziej * szybszy *, ale myślę, że ten sposób będzie lepszy, użyje go. dzięki! – QuantumHoneybees

+0

hooray, edytor OP, który faktycznie zapewnia dobrze odebraną odpowiedź, a nie tylko edycję, aby zwiększyć liczbę powtórzeń. rzadko spotykany. – aremvee

+0

@Usuwanie - .reverse() ta funkcja nie jest obsługiwana w swift3. Ktoś może pomóc w tym samym pytaniu? –

14

Czy zamiast tego można użyć numeru filter?

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

Ach tak, masz rację! Zmodyfikuję, dzięki! –

+0

Nowa tablica powinna mieć nazwę 'greaterThan4';) W każdym razie jest to poprawny sposób rozwiązania problemu. –

+0

O tak, tak! funkcja, która to nazywa nazywa się "filterArray". Nigdy nie nawiązałem połączenia haha. Ale potrzebuję również, aby przefiltrowane wyniki zostały dołączone do końca. Jakieś sugestie? – QuantumHoneybees

10

Jeśli chcesz kontynuować używając for -loop można wyliczyć zarówno wskaźnik nad elementem i używając enumerate:

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

Chociaż w zależności od tego, co robisz w pętli filter metoda może być lepszym pomysłem.

+7

To zły pomysł, w pewnych okolicznościach natkniesz się na pułapkę poza zasięgiem, na przykład wypróbuj tablicę '[6, 5, 4, 3, 2, 1]'. Powodem jest to, że tablica jest modyfikowana w pętli, ale indeks nie jest dostosowywany. – vadian

0

Jeśli pętla idzie do przodu ...

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) 
    } 

}