2010-11-19 32 views
2

Je travaillais sur l'écriture d'un petit fragment de code pour inverser une chaîne à l'aide de la liste des ajouts et de la pop.Problème avec la liste d'inversion à l'aide de list.pop()

Le script que j'ai écrit comme suit:

someStr = raw_input("Enter some string here:") 
strList = [] 
for c in someStr: 
    strList.append(c) 

print strList 

reverseCharList = [] 
for someChar in strList: 
    reverseCharList.append(strList.pop()) 

print reverseCharList 

Quand j'entre une chaîne ABCD, la sortie qui est renvoyée est [d, c].

Je sais que je suis en train de muter la liste que je suis en train d'itérer mais quelqu'un peut-il expliquer pourquoi les caractères 'a' et 'b' ne sont pas affichés ici?

Merci

+0

Ceci est un excellent exercice pour apprendre la récursivité! – Chris

+2

Juste pour être sûr: vous connaissez ['] .reverse()', n'est-ce pas? – nmichaels

+0

@Nathon - Oui, je le fais. Je voulais juste savoir la raison de l'écart dans la sortie. –

Répondre

3

Que diriez-vous d'une simple inversion de chaîne.

>>> x = 'abcd' 
>>> x[::-1] 
'dcba' 
>>> 

Sur votre code:

Ne jamais muter la liste sur laquelle vous itérez avec. Cela peut causer des erreurs subtiles.

>>> strList = [1, 2, 3, 4, 5] 
>>> reverseCharList = [] 
>>> for someChar in strList: 
...  print strList 
...  reverseCharList.append(strList.pop()) 
...  print strList 
... 
[1, 2, 3, 4, 5] <-- Iteration 1 
[1, 2, 3, 4] 
[1, 2, 3, 4]  <-- Iteration 2 
[1, 2, 3] 
[1, 2, 3]   <-- Iteration 3 
[1, 2] 

Voir ci-après. Puisque vous utilisez l'itérateur (pour .. dans ..). Vous pouvez voir directement les détails de l'itérateur et la façon dont la liste se mute avec l'itérateur.

>>> strList = [1, 2, 3, 4, 5] 
>>> k = strList.__iter__() 
>>> k.next() 
1 
>>> k.__length_hint__() <--- Still 4 to go 
4 
>>> strList.pop()   <---- You pop an element 
5 
>>> k.__length_hint__() <----- Now only 3 to go 
3 
>>> 
>>> k.next() 
2 
>>> k.__length_hint__() 
2 
+0

Merci pour la version alternative.Je voulais juste savoir quel est le problème avec l'extrait que j'ai posté –

+1

'' .join (reverse ('abcd')) fait aussi la même chose, mais selon timeit le faire avec la liste tranchage l'opérateur est d'environ 9 fois plus rapide – Imran

+0

parfait Merci pour l'explication –

5
for someChar in strList: 
    reverseCharList.append(strList.pop()) 

est essentiellement le même que:

i = 0 
while i < len(strList): 
    reverseCharList.append(strList.pop()) 
    i += 1 

première itération i est 0, len (strList) est de 4, et vous pop + append 'd'.

La deuxième itération est 1, len (strList) vaut 3 et vous ajoutez + c '.

Troisième itération i est 2, len (strList) est 2, donc la condition de boucle échoue et vous avez terminé.

(Ceci est vraiment fait avec un itérateur sur la liste, pas une variable locale « i ». Je l'ai montré ainsi pour plus de clarté.)

Si vous souhaitez manipuler la séquence que vous nous parcourons il est généralement préférable d'utiliser une boucle while. par exemple:

while strList: 
    reverseCharList.append(strList.pop()) 
+0

Ceci est une excellente explication y at-il un endroit que je peux regarder les détails sur la façon dont la for-in constructeur est implémenté en Python en utilisant itérateurs –

+0

@sc_ray!..?: J'ai inclus une simple illustration de l'effet de l'itérateur sur le changement de séquence. – pyfunc

1

Vous raccourcissez la liste lorsque vous ouvrez.

reverseCharList = [] 
while strList: 
    reverseCharList.append(strList.pop()) 
1

Une version simple recersive:

def reverse(the_list): 
    if not the_list: 
     return [] 
    return [the_list.pop()] + reverse(the_list) 

Bien sûr, [].reverse() est plus rapide.