Python遍历列表删除指定字典未删尽的原因及解决方法
遍历列表删除元素时遗漏最后一个元素的原因及解决办法
原代码与运行结果
原代码:
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)
运行结果:
[{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}, {'label': 'bad_stuff'}]
为什么最后一个bad_stuff没被删除?
核心原因是在遍历列表的同时直接修改原列表,会打乱迭代器的索引逻辑。具体过程如下:
- 初始列表长度为6,迭代器从索引0开始遍历。
- 第一次遇到索引0的
bad_stuff,执行remove后,列表所有元素向前移动一位,原索引4、5的bad_stuff现在变成索引3、4。 - 迭代器继续走到下一个索引(此时是1),对应原列表的索引1(
cat),依次遍历完索引2、3的cat。 - 当迭代器走到索引3时,对应现在列表的索引3(原索引4的
bad_stuff),执行remove后,列表长度变为4,原索引5的bad_stuff现在在索引3的位置。 - 此时迭代器的下一个目标索引是4,但列表长度已经是4,循环直接结束,导致最后一个
bad_stuff从未被迭代到,自然没被删除。
解决办法
这里提供三种常用的可行方案:
1. 遍历列表的副本
通过list(shapes)创建原列表的副本,遍历副本时修改原列表,不会影响迭代过程:
shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}] for elem in list(shapes): if elem['label'] == "bad_stuff": shapes.remove(elem) print(shapes) # 输出: [{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}]
2. 使用列表推导式(推荐)
这是Python中最简洁高效的方式,直接生成过滤后的新列表:
shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}] shapes = [elem for elem in shapes if elem['label'] != "bad_stuff"] print(shapes) # 输出: [{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}]
3. 反向遍历列表
从列表末尾开始向前遍历,这样删除元素时不会影响未遍历到的元素索引:
shapes = [{"label": "bad_stuff"}, {"label": "cat"}, {"label": "cat"},{"label": "cat"}, {"label": "bad_stuff"}, {"label": "bad_stuff"}] for i in range(len(shapes)-1, -1, -1): if shapes[i]['label'] == "bad_stuff": del shapes[i] print(shapes) # 输出: [{'label': 'cat'}, {'label': 'cat'}, {'label': 'cat'}]
内容的提问来源于stack exchange,提问作者Johan hvn
相关产品推荐
相关产品推荐

