【问题标题】:How to delete an element from a list while iterating over it in Python?如何在 Python 中迭代列表中的元素时删除它?
【发布时间】:2011-01-27 09:52:08
【问题描述】:

给定一个数字列表:

L = [1, 2, 3, 4, 5]

如何在迭代时从列表中删除一个元素,比如说 3?

我尝试了以下代码,但没有成功:

for el in L:
    if el == 3:
        del el

有什么想法吗?

【问题讨论】:

  • 这个询问不是很好或通用的,因为它只询问删除匹配特定值的第一个元素,Python 已经有 L.remove(3) 内置或列表推导。但是这个询问不会涵盖所有更一般的情况,例如 “删除排序列表中重复的相邻值”

标签: python


【解决方案1】:

最好的做法通常是建设性地进行——建立你想要的项目的新列表,而不是删除你不想要的项目。例如:

L[:] = [el for el in L if el != 3]

列表解析构建所需的列表并分配给“整个列表切片”L[:],确保您只是重新绑定名称,而是完全替换 内容,因此效果与您想要执行的“删除”完全相同。这也很快。

如果您绝对不惜一切代价必须进行删除,那么一种微妙的方法可能会奏效:

>>> ndel = 0
>>> for i, el in enumerate(list(L)):
...    if el==3:
...      del L[i-ndel]
...      ndel += 1

没有任何地方像 listcomp 方法那样优雅、干净、简单或性能良好,但它确实可以完成工作(尽管乍一看它的正确性并不明显,实际上我在编辑之前就错了!-)。 “不惜一切代价”在这里适用;-)。

在“必须删除”的情况下,循环使用索引代替项目是另一种较差但可行的方法 - 但请记住在这种情况下反转索引...:

for i in reversed(range(len(L))):
  if L[i] == 3: del L[i]

确实,这是reversed 的主要用例,当时我们正在讨论是否添加该内置函数——reversed(range(... 在没有reversed 的情况下并非易事,并且在列表中循环反向顺序有时很有用。另一种选择

for i in range(len(L) - 1, -1, -1):

真的很容易出错;-)。

不过,我在此答案开头推荐的 listcomp 在检查替代方案时看起来越来越好,不是吗?-)。

【讨论】:

  • 好主意。我没有想到。谢谢你,亚历克斯! :)
  • 第二种方法会在有多个要删除的元素时删除错误的元素,因为第一次删除后索引会发生变化。
  • @interjay,+1:你说得对,我编辑以弥补这一点(不幸的是 reversed(enumerate(... 不起作用——enumerate 是一个可迭代但不是一个序列,reversed需要一个序列作为它的参数)。
【解决方案2】:
for el in L:
    if el == 2:
        del L[el]

【讨论】:

  • 需要枚举以便索引L[idx]。
  • 不,这确实会以非常奇怪的方式表现——如果完全不相关的项目等于2,则删除 L 的“第三项”(可能不止一次),并且经常跳过 L 中的一个项目进行此类删除。调试真是一场噩梦……!-)
猜你喜欢
  • 2016-11-21
  • 2018-07-18
  • 2021-07-16
  • 2010-12-07
  • 2013-01-29
  • 2019-05-02
  • 1970-01-01
  • 2011-04-02
相关资源
最近更新 更多