0

I have this code:

test = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"]

for i in test:
    if i not in ["C","D"]:
        test.remove(i)

print(test)

I was expecting to get ['C','D'] as a result of running the code above, however I am getting this ['B', 'C', 'D', 'F', 'H', 'J', 'L', 'N']

How can I successfully loop through a list of strings and delete the elements I don't need using Python 3?

NOTE: I don't want to use comprehension lists

thanks

masber
  • 2,875
  • 7
  • 29
  • 49
  • 5
    Possible duplicate of [Remove items from a list while iterating in Python](http://stackoverflow.com/questions/1207406/remove-items-from-a-list-while-iterating-in-python) – awesoon Apr 02 '16 at 10:49
  • @soon I don't want to use comprehension lists. thank you – masber Apr 02 '16 at 10:55
  • Any reason not to use list comprehensions? – awesoon Apr 02 '16 at 11:33
  • @soon this example is just an example of another piece of code and I believe using list comprehension will make my code more difficult to read – masber Apr 02 '16 at 12:06

2 Answers2

3

When removing from lists in other languages, I used to reverse walk the list:

test = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"]

for i in reversed(test):
    if i not in ["C","D"]:
        test.remove(i)

print(test)

Note that reversed will create a new list so this might not be the best solution for large lists. Now, since you already walk a copy of your list, and if you need to parse in the correct order, you can use copy:

import copy
for i in copy.copy(test):
    if i not in ["C","D"]:
        test.remove(i)

and to avoid the import (from here):

for i in test[:]:
    if i not in ["C","D"]:
        test.remove(i)

Finally, the best solution for me, is a traditional, in-place reverse iteration without copying the list ("borrowed" and modified from this answer)

for i in range(len(test) - 1, -1, -1):
    if test[i] not in ["C","D"]:
        del test[i]
Community
  • 1
  • 1
urban
  • 5,392
  • 3
  • 19
  • 45
0

First loop: i = 'A', i not in ['C', 'D'] -> remove i. Now the first item of test is 'B'. So in the next loop i will be equal to 'C'. That is where things gone wrong...

  • I know this but this behaviour doesn't seem to occur when I am using a list of int. – masber Apr 02 '16 at 12:37
  • It will occur no matter what kind of list. You can use pdb to debug and check yourself :') –  Apr 03 '16 at 01:30