我正在迭代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)
为了清楚起见,也为了那些认为[:]
表示法的使用过于混乱或模糊的人,这里有一个更明确的替代方法。 理论上,它在空间和时间方面的表现应该与上面的单行程序相同。
temp = []
while somelist:
x = somelist.pop()
if not determine(x):
temp.append(x)
while temp:
somelist.append(templist.pop())
它还可以在可能没有Python列表的替换项功能的其他语言中工作,只需进行最少的修改。 例如,并非所有语言都像Python那样将空列表转换为false
。 您可以用while somelist:
替换更明确的内容,如while len(somelist)>; 0:
。
建议列表理解的答案几乎是正确的--除了它们建立一个全新的列表,然后给它与旧列表相同的名称之外,它们不会在适当的位置修改旧列表。 这与通过选择性删除(如@Lennart的建议)所做的不同--它更快,但是如果通过多个引用访问列表,那么您只是重置其中一个引用,而不改变列表对象本身,这一事实可能导致微妙的,灾难性的bug。
幸运的是,它非常容易获得列表理解的速度和就地更改所需的语义--只需代码:
somelist[:] = [tup for tup in somelist if determine(tup)]
请注意与其他答案的细微差别:这个答案不是分配给一个barename--而是分配给一个恰好是整个列表的列表片,从而替换了同一个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
[]