web-dev-qa-db-fra.com

Modifier la liste en itérant

l  = range(100)                         
for i in l:                         
    print i,                         
    print l.pop(0),                  
    print l.pop(0)

Le code python ci-dessus donne une sortie assez différente de celle attendue. Je souhaite boucler des éléments afin de pouvoir ignorer un élément lors de la mise en boucle.

S'il vous plaît, expliquez.

49
Xolve

J'ai déjà été mordu par le code "intelligent" (de quelqu'un d'autre) qui tente de modifier une liste tout en l'itérant. J'ai résolu de ne jamais le faire en aucune circonstance.

Vous pouvez utiliser l'opérateur de tranche mylist[::3] pour passer à chaque troisième élément de votre liste.

mylist = [i for i in range(100)]
for i in mylist[::3]:
  print(i),

D'autres points sur mon exemple concernent la nouvelle syntaxe dans python 3.0

  • J'utilise une compréhension de liste pour définir mylist car cela fonctionne en Python 3.0 (voir ci-dessous)
  • print est une fonction de python 3.0

Python 3.0 range () se comporte désormais comme xrange (), sauf que cela fonctionne avec des valeurs de taille arbitraire. Ce dernier n'existe plus.

40
Ewan Todd

Ne modifiez jamais le conteneur sur lequel vous bouclez, car les itérateurs de ce conteneur ne seront pas informés de vos modifications et, comme vous l'avez remarqué, cela produira probablement une boucle très différente et/ou incorrecte. Dans les cas normaux, boucler sur une copie du conteneur peut aider, mais dans votre cas, il est clair que vous ne pas voulez, car le conteneur sera vide au bout de 50 étapes de la boucle et si vous essayez ensuite une nouvelle fois, vous aurez une exception.

Quel est le problème, MAIS il est clair, quel comportement essayez-vous d’obtenir, le cas échéant?! Peut-être que vous pouvez exprimer vos désirs avec un while...?

i = 0
while i < len(some_list):
    print i,                         
    print some_list.pop(0),                  
    print some_list.pop(0)
49
Alex Martelli

La règle générale est que vous ne modifiez pas une collection/un tableau/une liste en le parcourant. 

Utilisez une liste secondaire pour stocker les éléments sur lesquels vous souhaitez agir et exécuter cette logique dans une boucle après votre boucle initiale.

11
Paul Sasik

Essaye ça. Cela évite de muter une chose que vous parcourez, qui est généralement une odeur de code.

for i in xrange(0, 100, 3):
    print i

Voir xrange .

8
Hank Gay

Utilisez une boucle while qui vérifie la véracité du tableau:

while array:
    value = array.pop(0)
    # do some calculation here

Et il devrait le faire sans aucune erreur ou comportement amusant.

8
Eugene Eeo

Je suppose que c'est ce que vous voulez:

l  = range(100)  
index = 0                       
for i in l:                         
    print i,              
    try:
        print l.pop(index+1),                  
        print l.pop(index+1)
    except:
        pass
    index += 1

Il est assez pratique de coder lorsque le nombre d'éléments à supprimer est une décision d'exécution .. .. Mais il fonctionne avec une très mauvaise efficacité et le code est difficile à maintenir.

1
York Chang

Cette syntaxe de tranche crée une copie de la liste et fait ce que vous voulez:

l  = range(100)  
for i in l[:]:  
    print i,  
    print l.pop(0),  
    print l.pop(0)
0
thethinman