web-dev-qa-db-fra.com

Comment écrire une boucle for dans Swift 3 pour un tableau que je modifie pendant la boucle for?

Donc, j'ai une boucle for qui ressemble à ceci:

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

Cela fonctionnait. Mais lorsque je l'ai changée pour la syntaxe préférée Swift 3.0:

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

Je reçois une exception IOOBE sur un tableau car il ne vérifie pas le nombre et continue jusqu'à ce que le results.count d'origine soit obtenu.

Comment puis-je réparer ça? Cela fonctionne maintenant, mais je ne veux pas avoir de problèmes à l'avenir.

38
QuantumHoneybees

Tandis que la solution utilisant filter est une solution fine et plus Swift-ly, il existe un autre moyen, si vous utilisez for-in, vous le souhaitez toujours:

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)

Résultat:

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

Nous pourrions également omettre cette ligne i -= 1.

Le problème avec removeAtIndex dans la boucle est qu’il ne fera pas que le tableau se réindexe lui-même sur place et provoque ainsi une exception tableau hors limites en raison de count ne pas être mis à jour.

En effectuant un déplacement en arrière, l'exception hors limites peut donc être évitée.

66
Unheilig

Pourriez-vous utiliser un filter à la place?

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

Si vous souhaitez continuer à utiliser une boucle for-, vous pouvez énumérer à la fois l'index et l'élément à l'aide de enumerate:

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

Bien que, selon ce que vous faites dans votre boucle, la méthode filter pourrait être une meilleure idée.

9
Luka Jacobowitz

Si votre boucle avance ...

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

}
0
Miguel Herrero