52 votes

Comment écrire un for-loop en Swift 3 pour un tableau que je modifie pendant le for-loop ?

Donc, j'ai un for-loop qui ressemble à ça :

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

Ça marchait avant. Mais quand je l'ai changé pour la syntaxe préférée de Swift 3.0 :

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

J'obtiens une exception IOOBE parce qu'il ne revérifie pas le compte et continue jusqu'à ce que l'objet original soit atteint. results.count .

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

0 votes

Ce code ne se plaint pas pour var i in 0..<results.count { if (results[i] < 5) { results.removeAtIndex(i) i -= 1 } }

0 votes

Je ne me souviens pas avoir eu un problème avec cette boucle pendant les 25 dernières années.

84voto

Unheilig Points 3227

Alors que la solution faisant appel à filter est une bonne solution et c'est plus Swift-ly il y a un autre moyen, si l'on utilise la fonction for-in est, néanmoins, toujours souhaitée :

func removeBelow(value: Int) {
    var results = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

    for i in (0 ..< results.count).reversed() {
        if (results[i] < value) {
            results.remove(at: i)
        }
    }

    print(results)
}

removeBelow(value: 5)

Résultat :

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

Le problème avec removeAtIndex à l'intérieur de la boucle est qu'il n'y aura pas de réindexation du tableau. en place et causant ainsi une exception de tableau hors limites due à count n'est pas mis à jour.

En parcourant le chemin à l'envers, l'exception hors limites peut ainsi être évitée.

2 votes

Oh mon Dieu... c'est vraiment intelligent. Ouais, je sais que la méthode du filtre serait plus... rapidement mais je pense que cette façon s'applique mieux, je vais l'utiliser. merci !

0 votes

Hourra, un rédacteur d'un PO qui fournit réellement une réponse bien reçue, et pas seulement une édition pour augmenter la réputation. rare.

0 votes

@Unheiling - .reverse() cette fonction n'est pas supportée dans swift3. Quelqu'un peut plus aider sur la même question ?

19voto

Brandon Shega Points 549

Pourriez-vous utiliser un filter à la place ?

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

1 votes

Le nouveau tableau doit être nommé greaterThan4 ;) Quoi qu'il en soit, c'est la façon correcte de résoudre le problème.

0 votes

Ah oui, c'est vrai ! La fonction qui appelle cela s'appelle "filterArray". Je n'avais jamais fait le rapprochement. Mais j'ai aussi besoin que les résultats filtrés soient ajoutés à la fin. Des suggestions ?

15voto

Luka Jacobowitz Points 3990

Si vous voulez continuer à utiliser un for -vous pouvez énumérer à la fois l'indice et l'élément en utilisant la fonction enumerate :

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

Bien qu'en fonction de ce que vous faites dans votre boucle, la filter pourrait être une meilleure idée.

8 votes

C'est une mauvaise idée, vous vous retrouverez dans le piège de la sortie de gamme dans certaines circonstances, essayez par exemple le tableau suivant [6, 5, 4, 3, 2, 1] . La raison en est que le tableau est modifié dans la boucle mais l'index n'est pas ajusté.

1voto

Miguel Herrero Points 1

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

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X