0

I have a for loop that is supposed to remove all string-items from a list that contain '0'. However, it only removes some of them.

for e in l:
    if '0' in e:
        l.remove(e)

In my case l is a list of integers turned into strings, In my test run this list looked like this before executing the for loop:

['12345', '23456', '34567', '45678', '56789', '67891', '78910', '89101', '91011', '10111', '01112', '11121', '11214', '12141', '21414', '14145', '41455', '14555', '45550', '55500', '55008', '50088', '00887']

And after that like this:

['12345', '23456', '34567', '45678', '56789', '67891', '89101', '10111', '11121', '11214', '12141', '21414', '14145', '41455', '14555', '55500', '50088']

There were only six elements removed, some elements wich still contain '0' are however still left.

Christian Singer
  • 255
  • 4
  • 12
  • 5
    Do not *alter* a list while *iterating* over it. Furthermore using `.remove(..)` makes it an *O(n^2)* algorithm. – Willem Van Onsem Jul 21 '17 at 14:55
  • 1
    If you are looking for an explanation for why it didn't work, its because when it removes an element, every single other element in the list is moved over one, meaning that one element will be skipped in the next iteration, so if two in a row had a `0` then the second one would be skipped by the for loop – Professor_Joykill Jul 21 '17 at 15:01

3 Answers3

3

do not remove element during iteration

l =  ['12345', '23456', '34567', '45678', '56789', '67891', '78910', '89101', '91011', '10111', '01112', '11121', '11214', '12141', '21414', '14145', '41455', '14555', '45550', '55500', '55008', '50088', '00887']

new_l = [ele for ele in l if '0' not in ele] 

['12345', '23456', '34567', '45678', '56789', '67891', '11121', '11214', '12141', '21414', '14145', '41455', '14555']
galaxyan
  • 5,119
  • 2
  • 15
  • 36
2

Its a bad idea to change the list while iterating over it. Instead you can create a new list and add to it only the elements in l that do not contain 0, as follows:

res=[]

for e in l:
    if '0' not in e:
        res.append(e)

You can also do it with list comprehension:

res=[e for e in l if '0' not in e]
Miriam Farber
  • 16,192
  • 11
  • 51
  • 69
0

It is happening because whenever you have 2 continuous elements that need to be removed,

for ex- list is a b c d and you want to remove b and c and current position is at b.
So when you delete b the list becomes a c d with current position at c.

As you are iterating , the current position then moves to d and c get skipped.

The solution as suggested by ChristianDean is to make a new list with the values that you want to keep

res = [el for el in l if '0' not in el]
Tanuj Yadav
  • 1,101
  • 11
  • 21