Removing all lists in a list, that match a particular condition

Question:

I am a beginner in Python and got a little stuck on a problem. It required me to remove all the items (in this particular case lists), that met a simple math requirement.
Like for example: the sum of all elements is not equal to n.


So I tried this…

a_list = [[1, 1, 1], [3, 0, 0]]
for i in a_list:
    if sum(i) != 3:
        continue
    else:
        a_list.remove(i)
print(a_list)

But all I got was… [[3, 0, 0]]


Why did my program delete only the first object the met the condition, although the for loop is iterating through the whole list?

Asked By: Butyl

||

Answers:

General rule: Never ever modify a list while you iterate over it. It will f up the iteration. Always make copys (of the references or the objects). Also the if else is a bit useless as you could avoid one branch if you just inverted the condition.
What happens here is: Python deletes the first list, tries to access the list at index 1 but since it is now at index 0 it aborts the iteration thus leaving the second list in place.

Answered By: C. Dautermann
a_list = [[1, 1, 1], [3, 0, 0]]
a_list = [a_list.remove(i) for i in a_list if sum(i)==3]
print(a_list)

>>> [None]
Answered By: DialFrost

In brief, the reason you are getting the strange result is because you are iterating over your list while deleting its content.

Explanation

First time your loop runs, the internal iterator is pointing at the first element of the loop, which is [1,1,1].

Since this element fails the initial condition, it is removed. When it is removed, the list internally will shift the next element ([3,0,0]) to the left to now occupy the position of the element that was removed.

Now the for-loop will attempt to go to the next element, but it now thinks that it has reached the end of the list, so it stops, and you are left with [3,0,0].

Solution

Instead of modifying the original list, the more pythonic solution is to create a new list consisting of just the elements you wanted, while ignoring the ones you don’t want, and this is often accomplished by using list-comprehension.

a_list = [[1, 1, 1], [3, 0, 0]]
filtered_a_list = [elem for elem in a_list if sum(elem) != 3]

You can also do it without list-comprehension:

a_list = [[1, 1, 1], [3, 0, 0]]
filtered_a_list = []
for elem in a_list:
  if sum(elem) != 3:
    filtered_a_list.append(elem)
Answered By: smac89
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.