0

When running this python code:

shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}]
for elem in shapes:
    if elem['label'] == "bad_stuff":
        shapes.remove(elem)

... I get this result:

[{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}, {'label': 'bad_stuff'}]

Why does not the code remove the last element in the list and how can I solve it?

Johan hvn
  • 318
  • 1
  • 2
  • 11
  • 2
    https://stackoverflow.com/questions/5384914/how-do-i-delete-items-from-a-dictionary-while-iterating-over-it – mont_ Oct 19 '22 at 12:26
  • @mont_ `shapes` is a list, not a dictionary. – 001 Oct 19 '22 at 12:37
  • 1
    Does this answer your question? [How to remove items from a list while iterating?](https://stackoverflow.com/questions/1207406/how-to-remove-items-from-a-list-while-iterating) – 001 Oct 19 '22 at 12:37
  • @JohnnyMopp - it's the same issue. If you modify the object you're iterating over you'll get weird things happening. – Tim Tisdall Oct 19 '22 at 12:38
  • @TimTisdall Sure, I'm not arguing that point. It's just the link in mont_'s comment is specifically for dictionaries. – 001 Oct 19 '22 at 12:39

3 Answers3

2

Because you are modifying list during for loop. Let's see what's happening in your code:

On 1st interation it removes shapes[0] item. 2, 3, 4 iterations do not satisfy condition, so passed. On 5th iteration the elem is {"label": "bad_stuff"}, and your shapes looks like this:

[{"label": "cat"}, {"label": "cat"},{"label": "cat"}, **{"label": "bad_stuff"}**, {"label": "bad_stuff"}]

So when you remove(elem) on this step, it removes last item in the list. And since you removed last item - iteation stops.

There is solution to your problem:

shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}]

cat_shapes = []
for elem in shapes:
    if elem['label'] != "bad_stuff":
        cat_shapes.append(elem)

Another solution mentioned in comments by DanielB :

cat_shapes = [elem for elem in shapes if elem['label'] != "bad_stuff"]
  • A [list comprehension](https://docs.python.org/3/tutorial/datastructures.html#list-comprehensions) would also be a good solution here. – DanielB Oct 19 '22 at 12:47
0

You can do this with filter,

list(filter(lambda x:x['label'] != 'bad_stuff', shapes))
# [{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}]
Rahul K P
  • 15,740
  • 4
  • 35
  • 52
0

If you want to remove matching elements from list please check below code

def remove_bad_stuff(shapes, remove_value):
    for elem in shapes:
        if elem['label'] == remove_value:
            shapes.remove(elem)
            remove_bad_stuff(shapes, remove_value)

shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}]
remove_bad_stuff(shapes,"bad_stuff")
print(shapes)
Neo-coder
  • 7,715
  • 4
  • 33
  • 52