0

Given a Python list, I'd like to remove "bad" elements. For example, given a list of lists of integers, I'd like to remove lists beginning with a negative integer. Here's an attempt and failure:

S=[[1,1],[2,1],[-1,1],[-2,1]]

for s in S:    
    if s[0]<0:
        S.remove(s)

which returns

[[1, 1], [2, 1], [-2, 1]]

I'd like to know why the above code doesn't work as expected (it would be instructive), as well as the right way to do this. (I know that I can create a new list where I add those lists of S with positive first element, but I'd rather not make a new list unless necessary.)

TBRS
  • 81
  • 1
  • 2
  • 6
  • Removing values from a list while iterating can trip up the iterator, so your loop ends up skipping some of the elements. – Aran-Fey Sep 01 '18 at 15:42
  • use a list comprehension `[i for i in s if i[0] > 0]` – Abhi Sep 01 '18 at 15:46
  • Thanks. It does indeed happen to be a duplicate question. However, the linked answers don't really seem to explain what's going wrong. Is building a new list with the required conditions the standard way to solve such a problem? – TBRS Sep 01 '18 at 15:51
  • @TBRS when the loop finds `[-1,1]` at `index 2` based on the condition it will execute `S.remove(s)` so now the element after `[-1,1]` which is `[-2,1]` at `index 3` is moved one step down to `index 2` but the loop always moves to next index so in your case there's no element at `index 3`. That's the reason it fails to find `[-2,1]`. Hope that's clear. – Abhi Sep 01 '18 at 16:16
  • You can't really avoid creating a new list, which is why list comprehensions are the standard way of doing these kinds of things. (You could use a `while` loop with an index variable and decrement the index variable whenever you remove something from the list. But repeatedly removing something from a list is worse than building a new list.) – Aran-Fey Sep 01 '18 at 16:26
  • `del list[index]` – Nouman Sep 01 '18 at 17:13

0 Answers0