Removing the last list item in Python fails

I am trying to remove the last element of a list in Python:

di = {"a": 3, "children": [{"b": 5}, {"c": 6}]} for el in di['children']: di['children'].remove(el) 

What i expect

 print di {'a': 3, 'children: []} 

But I get

 print di {'a': 3, 'children': [{'c': 6}]} 

Does anyone have an idea what is going wrong?

+4
source share
7 answers

As everyone else explained, you cannot change the list, iterate over it.

You can change the list, iterate over its copy, but it's probably best to just create a new filtered list:

 di = {"a": 3, "children": [{"b": 5}, {"c": 6}]} di['children'] = [el for el in di['children'] if el not in di['children']] 

Why is it better? Well, that means you avoid mutating the list, which makes your code easier to reason about, easier to track, usually easier to write, and often faster and more economical. The fact that you don’t have to worry about problems with mutation and repetition is a great example of the easier to reason part.

In some cases, it becomes harder to write, or slower, or less economical, so this is just a guideline, not a hard rule. But it’s always, at least, worth considering: β€œCan I rewrite this as an immutable filter instead of a mutator,” even if the answer may sometimes be β€œno.”

And really, isn't your algorithm guaranteed to be equivalent to simply emptying everything? In this case:

 di = {"a": 3, "children": [{"b": 5}, {"c": 6}]} di['children'] = [] 
+11
source

You should not change the list as it repeats. Instead, you should iterate over the copy. See python docs .

Try it...

 di = {"a": 3, "children": [{"b": 5}, {"c": 6}]} for el in di['children'][:]: di['children'].remove(el) 
+6
source

You change the list when you iterate over it - when you delete the first record, the second record becomes the first, and the end of the list is reached. Use instead:

 del di["children"][:] 

This will keep the original list (unlike di["children"] = [] ), so if you have other references to them, they will also reflect truncation.

+6
source

You can only delete items in a loop when you scroll the list in the opposite direction.

So, I think just wrap di ['children'] in a reverse () iterator like this

 for el in reversed(di['children']): 

This is because deleting an element causes the numbering of the elements to change, and all subsequent elements will have a minus 1. But if you go back, you do not need to keep track of the indices of the following elements, approximately from the elements before deleting.

+4
source

You change the list when you iterate over it, which is a bad idea.

Try iterating over a copy of the list by removing items from the original.

+2
source
 del di['children'][1] 

Delete the last item in the list.

+2
source
  for i in di: if type(di[i])==list: di[i]=[] 
0
source

Source: https://habr.com/ru/post/1443112/


All Articles