我在Python中迭代一个元组列表,并试图删除它们,如果它们满足某些条件。
for tup in somelist:
if determine(tup):
code_to_remove_tup
我应该用什么来代替code_to_remove_tup?我不知道怎么用这种方式把东西拿掉。
我在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)]
或者,通过分配slice somlist[:],你可以改变现有的列表,只包含你想要的项:
somelist[:] = [x for x in somelist if not determine(x)]
如果对某个列表的其他引用需要反映更改,则此方法可能很有用。
你也可以使用itertools来代替理解函数。在Python 2中:
from itertools import ifilterfalse
somelist[:] = ifilterfalse(determine, somelist)
或者在python3中:
from itertools import filterfalse
somelist[:] = filterfalse(determine, somelist)
其他回答
对于这样的示例,最好的方法是列表理解
somelist = [tup for tup in somelist if determine(tup)]
如果您要做的事情比调用确定函数更复杂,我更喜欢构造一个新列表,并在执行过程中简单地追加它。例如
newlist = []
for tup in somelist:
# lots of code here, possibly setting things up for calling determine
if determine(tup):
newlist.append(tup)
somelist = newlist
使用remove复制列表可能会使您的代码看起来更简洁,如下面的其中一个答案所述。对于非常大的列表,您绝对不应该这样做,因为这涉及到首先复制整个列表,并对被删除的每个元素执行O(n)删除操作,使其成为O(n^2)算法。
for tup in somelist[:]:
# lots of code here, possibly setting things up for calling determine
if determine(tup):
newlist.append(tup)
我需要用一个巨大的列表来做这件事,复制列表似乎很昂贵,特别是因为在我的情况下,删除的数量与保留的项目相比很少。我采用了这种低层次的方法。
array = [lots of stuff]
arraySize = len(array)
i = 0
while i < arraySize:
if someTest(array[i]):
del array[i]
arraySize -= 1
else:
i += 1
我不知道的是,与复制一个大列表相比,几个删除操作的效率有多高。如果你有什么见解,请评论。
一个可能的解决方案,如果你不仅想删除一些东西,而且还想对单个循环中的所有元素做一些事情,这个解决方案很有用:
alist = ['good', 'bad', 'good', 'bad', 'good']
i = 0
for x in alist[:]:
if x == 'bad':
alist.pop(i)
i -= 1
# do something cool with x or just print x
print(x)
i += 1
for i in range(len(somelist) - 1, -1, -1):
if some_condition(somelist, i):
del somelist[i]
你需要向后走,否则就有点像锯掉你坐着的树枝:-)
Python 2用户:用xrange替换range以避免创建硬编码的列表
你可以反过来尝试for- loops,这样对于some_list,你就可以这样做:
list_len = len(some_list)
for i in range(list_len):
reverse_i = list_len - 1 - i
cur = some_list[reverse_i]
# some logic with cur element
if some_condition:
some_list.pop(reverse_i)
这样索引是对齐的,并且不会受到列表更新的影响(无论是否弹出cur元素)。