我在Python中迭代一个元组列表,并试图删除它们,如果它们满足某些条件。

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

我应该用什么来代替code_to_remove_tup?我不知道怎么用这种方式把东西拿掉。


当前回答

对于这样的示例,最好的方法是列表理解

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)

其他回答

对于这样的示例,最好的方法是列表理解

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

我不知道的是,与复制一个大列表相比,几个删除操作的效率有多高。如果你有什么见解,请评论。

其他答案是正确的,从你正在迭代的列表中删除通常是一个坏主意。反向迭代避免了一些陷阱,但是要遵循这样做的代码要困难得多,所以通常您最好使用列表理解或过滤器。

然而,有一种情况下,从您正在迭代的序列中删除元素是安全的:如果您在迭代时只删除一项。这可以通过返回或中断来确保。例如:

for i, item in enumerate(lst):
    if item % 4 == 0:
        foo(item)
        del lst[i]
        break

当您对满足某些条件的列表中的第一个项执行一些具有副作用的操作,然后立即从列表中删除该项时,这通常比列表推导式更容易理解。

如果希望在迭代时从列表中删除元素,请使用while循环,以便在每次删除后都可以更改当前索引和结束索引。

例子:

i = 0
length = len(list1)

while i < length:
    if condition:
        list1.remove(list1[i])
        i -= 1
        length -= 1

    i += 1

for循环将遍历一个索引…

假设你有一个清单,

[5, 7, 13, 29, 65, 91]

您使用了一个名为lis的列表变量。你用同样的方法来移除…

你的变量

lis = [5, 7, 13, 29, 35, 65, 91]
       0  1   2   3   4   5   6

在第5次迭代中,

你的数字35不是质数,所以你把它从列表中删除了。

lis.remove(y)

然后下一个值(65)移动到前一个索引。

lis = [5, 7, 13, 29, 65, 91]
       0  1   2   3   4   5

所以第四次迭代完成指针移动到第五次…

这就是为什么你的循环没有覆盖65,因为它已经移动到前一个索引。

因此,你不应该将一个列表引用到另一个变量中,它仍然引用原始变量而不是副本。

ite = lis # Don’t do it will reference instead copy

所以使用list[::]复制列表。

现在你会付出,

[5, 7, 13, 29]

问题是你在迭代过程中从列表中删除了一个值,然后你的列表索引就会崩溃。

所以你可以试试列表理解。

它支持所有的可迭代对象,如list, tuple, dict, string等。