0

I am iterating over a list of tuples in Python, and it seems to me that the middle element is being skipped somehow. Here is my block of code, with the goal to remove any tuples that have None as the second element:

print('List of tuples before modification: ' +str(list_of_tuples))
for refseq_tuple in list_of_tuples:
    print('tuple: ' +str(refseq_tuple))
    if refseq_tuple[1] == None:
        list_of_tuples.remove(refseq_tuple)
print('List of tuples after modification: ' +str(list_of_tuples))

And here is the output:

List of tuples before modification: [('100652761', None), ('100653343', None), ('3183', 0)]
tuple: ('100652761', None)
tuple: ('3183', 0)
List of tuples after modification: [('100653343', None), ('3183', 0)]

So...what is happening to the middle (2nd) element? It looks as though it isnt being iterated over at all, or it would print between the other two tuples.

Houdini
  • 3,442
  • 9
  • 31
  • 47
  • 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) – Martijn Pieters Jul 12 '13 at 14:36
  • 2
    You are modifying a list *while iterating*. The iterator index doesn't know you removed items and continues to increment and thus appears to skip items. – Martijn Pieters Jul 12 '13 at 14:37
  • 1
    Also, it's generally frowned upon to use equality to check for `None`. Use `is` instead. – Silas Ray Jul 12 '13 at 14:40
  • Ok sorry if its a duplicate, I did try searching first. Thanks all! Looks like list comprehension is the way to go. – Houdini Jul 12 '13 at 14:45

2 Answers2

1

You have changed the original list. So this time the index 1 refers to ('3183', 0).

>>> alist = [('100652761', None), ('100653343', None), ('3183', 0)]
>>> [x for x in alist if not x[1] is None]
[('3183', 0)]
>>> 
zhangyangyu
  • 8,520
  • 2
  • 33
  • 43
1

As others have pointed out, you are modifying the list while iterating it. However, you can accomplish what you are doing here with just a list comprehension (unless for some reason you really need to modify in place).

list_of_tuples = [tup for tup in list_of_tuples if tup[1] is not None]
Silas Ray
  • 25,682
  • 5
  • 48
  • 63
  • 1
    Even if you need to modify in place, using a slice assignment of a list comprehension (or better yet, a generator expression) is going to be better. – kindall Jul 12 '13 at 14:53