简体   繁体   English

删除Python中列表的最后一个元素失败

[英]Removing last element of a list in Python fails

I'm trying to remove the last element of a list in Python: 我正在尝试删除Python中列表的最后一个元素:

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

What I'd expect is 我期待的是

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

But what I get is 但我得到的是

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

Does anybody have an idea what's going wrong? 有人知道出了什么问题吗?

As everyone else has explained, you can't modify a list while iterating over it. 正如其他人所解释的那样,您无法在迭代时修改列表。

You can modify a list while iterating over a copy of it, but it's probably better to just generate 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 this better? 为什么这样更好? Well, it means you're avoiding mutating the list, which makes your code easier to reason about, easier to trace through, usually easier to write, and often faster and more space-efficient. 好吧,这意味着你要避免改变列表,这使你的代码更易于推理,更容易追踪,通常更容易编写,而且通常更快,更节省空间。 The fact that you don't have to worry about mutating-while-iterating problems is a perfect example of the "easier to reason about" part. 事实上,您不必担心迭代变异问题,这是“更容易推理”部分的完美示例。

In some cases, it does turn out to be harder to write, or slower, or less space-efficient, which is why this is just a guideline rather than a hard rule. 在某些情况下,它确实更难写,或更慢,或更少节省空间,这就是为什么这只是一个指导而不是硬规则。 But it's always at least worth thinking "can I rewrite this as an immutable filter instead of a mutator", even if the answer may sometimes turn out to be "no". 但它总是至少值得思考“我可以将其重写为不可变过滤器而不是变换器”,即使答案有时可能变成“不”。

Also really, isn't your algorithm guaranteed to be equivalent to just emptying the whole thing out? 还真的,是不是你的算法保证等同于将整个事情清空? In that case: 在这种情况下:

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

You shouldn't modify the list as you iterate it. 在迭代时不应修改列表。 You should instead iterate over a copy. 你应该迭代一个副本。 See the python docs . 请参阅python文档

Try this... 尝试这个...

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

You are modifying a list as you are iterating over it - when you remove the first entry, the second entry becomes the first and the end of the list has been reached. 您正在迭代它时修改列表 - 当您删除第一个条目时,第二个条目成为第一个,并且已到达列表的末尾。 Instead, use: 相反,使用:

del di["children"][:]

This will preserve the original list (unlike di["children"] = [] ) so if you have other references to them they will also reflect the truncation. 这将保留原始列表(与di["children"] = [] )因此,如果您有其他引用它们,它们也将反映截断。

You can only remove elements in the loop when you going through a list in backward direction. 您只能在向后浏览列表时删除循环中的元素。

So I think just wrap di['children'] in reversed() iterator like this 所以我认为只需将di ['children']包装在reverse()迭代器中就像这样

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

It's because removing element causes changing numeration of elements, and all following elements will have number minus 1. But, if you going backward, you shouldn't care about indexes of following elements, just about elements before deleted. 这是因为删除元素会导致元素的编号变化,并且所有后续元素的数字都会减去1.但是,如果你向后移动,你不应该关心以下元素的索引,只关心删除前的元素。

You're modifying the list as you iterate over it, which is a bad idea. 你在迭代它时修改列表,这是一个坏主意。

Try iterating over a copy of the list, while removing the elements from the original. 尝试迭代列表的副本,同时从原始元素中删除元素。

del di['children'][1]

删除列表中的最后一个元素。

 for i in di:
    if type(di[i])==list:
       di[i]=[]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM