协慌网

登录 贡献 社区

迭代时如何从列表中删除项目?

我正在迭代 Python 中的元组列表,并且如果它们符合某些条件,我会尝试删除它们。

for tup in somelist:
    if determine(tup):
         code_to_remove_tup

我应该用什么代替code_to_remove_tup ?我无法弄清楚如何以这种方式删除项目。

答案

您可以使用列表推导来创建仅包含您不想删除的元素的新列表:

somelist = [x for x in somelist if not determine(x)]

或者,通过分配切片somelist[:] ,您可以改变现有列表以仅包含所需的项目:

somelist[:] = [x for x in somelist if not determine(x)]

如果有到其他参考这种方法可能是有用的somelist需要反映这些变化。

您也可以使用itertools而不是理解。在 Python 2 中:

from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)

或者在 Python 3 中:

from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)

建议列表推导的答案几乎是正确的 - 除了它们构建一个全新的列表然后给它与旧列表相同的名称,它们不会修改旧的列表。这与你通过选择性删除所做的不同,就像在 @ Lennart 的建议中一样 - 它更快,但是如果你的列表是通过多个引用访问的,那么你只是重新安装其中一个引用而不是改变列表对象本身可能导致微妙的,灾难性的错误。

幸运的是,获得列表推导的速度和就地更改所需的语义非常容易 - 只需代码:

somelist[:] = [tup for tup in somelist if determine(tup)]

注意与其他答案的细微差别:这个没有分配到一个名字 - 它分配给恰好是整个列表的列表切片,从而替换同一个 Python 列表对象中的列表内容 ,而不是仅仅重新设置一个引用(从之前的列表对象到新列表对象)就像其他答案一样。

您需要获取列表的副本并首先迭代它,否则迭代将失败,结果可能是意外结果。

例如(取决于列表的类型):

for tup in somelist[:]:
    etc....

一个例子:

>>> somelist = range(10)
>>> for x in somelist:
...     somelist.remove(x)
>>> somelist
[1, 3, 5, 7, 9]

>>> somelist = range(10)
>>> for x in somelist[:]:
...     somelist.remove(x)
>>> somelist
[]