0

Here is the simple example

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

My intention was to print and element and remove it but it seems that the next element gets removed though that is also not true as unprinted element got restored after loop.
Can you explain this behaviour ?
Is this a bug or my method is incorrect ?
Is it possible to do in-place removal without using another copy of list ?
Thanks.

user1371666
  • 445
  • 1
  • 5
  • 18

1 Answers1

0
l =[(1,2),(3,4),(5,6)]

for i, v in enumerate(l):
    print (v)
    l[i] = ""

print ([x for x in l if x])

Output:

(1, 2)
(3, 4)
(5, 6)
[]

Briefly, if you remove a list element while you are iterating through, you change the index range. So you remove (1,2), then you skip (3,4) cause it is now at the index of removed element (1,2). So second iteration third element (5,6).

So no it is not a bug, and your method is certainly not correct for your needs!

Use enumerate, in my example, or alternatively:

for i in range(len(l)):
    print (l[i])
    l[i] = ""

print ([x for x in l if x])

In fact, you should never remove an element/index in list while iterating through. You can set the value at index to nothing "" then remove the empty elements.

Synthase
  • 5,849
  • 2
  • 12
  • 34
  • I definitely agree ```In fact, you should never remove an element/index in list while iterating through.```, but once in a while, I somewhat have to do that but with great caution. – Albert G Lieu Jan 16 '21 at 04:49
  • to Synthase , that was a nice explanation for behaviour . 'enumerate' solution replaces list element with empty string but list length is still same and list is not empty at the end . An empty list return 'not list' as true. Also, alternatively solution gave error 'TypeError: 'list' object cannot be interpreted as an integer' – user1371666 Jan 16 '21 at 05:53
  • Yes sorry I corrected for the alternative solution. Range(len(l)) and not range(l)! – Synthase Jan 16 '21 at 14:56