2010-03-29 4 views
7

J'essaie de transférer le contenu d'une liste à une autre, mais cela ne fonctionne pas et je ne sais pas pourquoi. Mon code ressemble à ceci:itération d'une liste en supprimant des éléments, certains éléments ne sont pas supprimés

list1 = [1, 2, 3, 4, 5, 6] 
list2 = [] 

for item in list1: 
    list2.append(item) 
    list1.remove(item) 

Mais si je le lance ma sortie ressemble à ceci:

>>> list1 
[2, 4, 6] 
>>> list2 
[1, 3, 5] 

Ma question est triple, je suppose: Pourquoi est-ce qui se passe, comment puis-je faire fonctionner , et suis-je en train de négliger une solution incroyablement simple comme une déclaration de «déménagement» ou quelque chose?

+0

Merci pour tous les types d'aide - c'est une belle explication concise de ce que je faisais mal et plusieurs options fix, que je vais se précipiter hors et tenter de mettre en œuvre maintenant. =) – potatocubed

Répondre

8

La raison est que vous êtes (ajoutant) et supprimant de la première liste où il devient plus petit. L'itérateur s'arrête donc avant que toute la liste puisse être franchie.

Pour obtenir ce que vous voulez, faites ceci:

list1 = [1, 2, 3, 4, 5, 6] 
list2 = [] 

# You couldn't just make 'list1_copy = list1', 
# because this would just copy (share) the reference. 
# (i.e. when you change list1_copy, list1 will also change) 

# this will make a (new) copy of list1 
# so you can happily iterate over it (without anything getting lost :) 
list1_copy = list1[:] 

for item in list1_copy: 
    list2.append(item) 
    list1.remove(item) 

Le list1[start:end:step] est le slicing syntax: lorsque vous quittez début vide la valeur par défaut à 0, lorsque vous quittez fin vide, il est le plus élevé possible valeur. Donc, list1 [:] signifie tout ce qu'il contient. (merci à Wallacoloo)

Comme certains mecs l'ont dit, vous pouvez aussi utiliser le extend -method de l'objet list pour copier la liste dans une autre, si c'était votre intention. (Mais j'ai choisi le chemin ci-dessus, parce que c'est proche de votre approche.)

Comme vous êtes nouveau sur python, j'ai quelque chose pour vous: Dive Into Python 3 - c'est gratuit et facile. - S'amuser!

+1

Et un lien pour expliquer l'indexation de la liste/découpage en tranches ('la liste [:]' est un exemple de découpage en tranches de liste): http://docs.python.org/tutorial/introduction.html#lists – Ponkadoodle

8

Vous supprimez des éléments de list1 pendant que vous les parcourez.

Cela demande des problèmes.

Essayez ceci:

>>> list1 = [1,2,3,4,5,6] 
>>> list2 = [] 
>>> list2 = list1[:] # we copy every element from list1 using a slice 
>>> del list1[:] # we delete every element from list1 
+2

le liste2 = [] n'est pas nécessaire –

1

Exactement comme dit ChristopheD.

pourrait le faire:

list1 = [1, 2, 3, 4, 5, 6] 
list2 = [] 

for item in list1: 
    list2.append(item) 

list1 = [] 

qui va list1 claire.

Modifier Il a mis à jour son message. Je vais laisser cela comme une légère alternative.

3

Vous ne devez pas modifier une liste pendant que vous la parcourez. Cela provoque l'itérateur pointer sur le mauvais élément. Après le traitement du premier élément, l'itérateur pointe sur index = 1, mais comme vous avez supprimé un élément, l'élément suivant est maintenant à l'index zéro, il sera donc ignoré. C'est pourquoi vous ne manipulez que tous les autres articles.

Essayez:

list2.extend(list1) # This appends all items from list1 to list2. 
del list1[:] # From ChristopheD's post. 
+0

Pour downvoter: Raison de downvote? S'il y a une erreur dans mon message, j'aimerais savoir de quoi il s'agit pour que je puisse apprendre pour l'avenir. –

1

En utilisant une compréhension de la liste:

list2 = [item for item in list1] 

Bind le nom list2 au même objet que list1:

list2 = list1 

(Notez que si vous modifiez le contenu de list1, list2 sera b e modifier en conséquence)

Créer une copie de list1 et de se lier au nom list2:.

list2 = list1[:] 

Dans ce cas list1 et list2 sont différents objets.

+0

La deuxième option ne fonctionnerait pas comme vous pensez qu'il (d'autant plus que vous voulez supprimer les éléments de list1) – ChristopheD

+0

@ChristopheD: Désolé, ma réponse pas claire. Quand je dis lie le nom list2 au même objet que list1, je supposais que OP saurait que list2 et list1 sont tous les deux des noms pour le même objet. –

+0

désolé, je peux avoir mal lu/mal interprété votre réponse puis – ChristopheD

1

Essayez ceci:

list1 = [1, 2, 3, 4, 5, 6] 
list2 = [] 

list2.extend(list1) 
list1[:] = [] 
4

compétences de débogage Essential: Ajouter print déclarations. (ou print fonctions en Python 3)

>>> list1= [1, 2, 3, 4, 5, 6] 
>>> for item in list1: 
...  print item 
...  list1.remove(item) 
...  print list1 
... 
1 
[2, 3, 4, 5, 6] 
3 
[2, 4, 5, 6] 
5 
[2, 4, 6] 

Remarquez que Python tente de parcourir les positions de la liste, mais vous gardez supprimer des éléments de la liste, ce qui rend les positions son sens.

Python sélectionne l'élément à la position 0 de la liste.

Vous supprimez ensuite l'élément, en changeant la liste.

Python prend alors l'élément en position 1 de la liste (apparaissant sauter un élément)

retirer alors cet élément, la modification de la liste.

Python prend alors l'élément à la position 2 de la liste (apparaissant sauter un élément)

Vous retirez alors l'élément, en changeant la liste.

Python voudrait alors choisir l'article à la position 3, mais il n'y a pas un tel article. Donc la boucle s'arrête.

1

Il est aussi l'humble fonction de copie (ou deepcopy si vous avez des objets complexes et non seulement des entiers dans la liste):

from copy import copy 

list2 = copy(list1) 

Vous pourriez obtenir une réponse plus appropriée si vous expliquez ce que vous essayez accomplir (à moins que vous ne soyez en train d'apprendre à propos des listes python). Les "variables" en Python ne sont que des noms/références, donc la copie destructrice que vous semblez vouloir faire semble plutôt étrange.Si vous voulez liste2 d'avoir les mêmes valeurs que list1 vous pouvez juste faire:

list2 = list1 # now they are both referring to the same list 

Et si après que vous souhaitez utiliser list1 pour quelque chose d'autre, vous pouvez juste faire:

list1 = ['A', 'B', 'C'] 
+0

Et puis liste2 serait également ' ['A', 'B', 'C'] '. La question est: pourquoi avoir deux listes alors ;-) – ChristopheD

+0

@ChristopheD: liste2 ne change pas - Je viens de vérifier. Un nouvel objet de liste est créé et lié au nom list1, laissant list2 non affecté. –

+0

@PreludeAndFugue: Hmm, bon point (jugé trop tôt sans penser appropriée) – ChristopheD

1

Comme vous peut voir dans d'autres réponses, vous essayez de modifier la liste tout en itérant sur elle. Cela ne fonctionne pas. Il y a plusieurs façons de copier une liste à une autre. Je l'ai fait quelques tests pour voir à quelle vitesse chaque approche est:

>>> timeit.Timer('list2 = list1[:]', 'list1 = range(10**3)').timeit(10**6) 
3.9134418964385986 

>>> timeit.Timer('list2 = []; list2.extend(list1)', 'list1 = range(10**3)').timeit(10**6) 
4.9082601070404053 

>>> timeit.Timer('list2 = copy.copy(list1)', 'import copy; list1 = range(10**3)').timeit(10**6) 
7.5023419857025146 

>>> timeit.Timer('list2 = [i for i in list1]', 'list1 = range(10**3)').timeit(10**6) 
95.697894811630249 

La syntaxe de tranche est le plus rapide. C'est beaucoup plus rapide que d'utiliser une compréhension de liste.

Pour effacer une liste, vous pouvez utiliser:

del list1[:] 
0

@potatocubed: La plupart des réponses données l'exemple trivial résoudre vous avez donné (« déplacer list1 à List2 »), mais ne l'explique pas vraiment le "pourquoi" du problème plus profond, qui modifie une liste au fur et à mesure que vous la parcourez. Etude de la réponse ... S. Lott

Questions connexes