106

我有一个清单

a = ["a", "b", "c", "d", "e"]

我想在 for 循环中删除此列表中的元素,如下所示:

for item in a:
    print(item)
    a.remove(item)

但它不起作用。我能做些什么?

4

6 回答 6

151

在使用循环对其进行迭代时,不允许从列表中删除元素for

重写代码的最佳方法取决于您要执行的操作。

例如,您的代码相当于:

for item in a:
    print(item)
a[:] = []

或者,您可以使用while循环:

while a:
    print(a.pop(0))

如果它们符合条件,我正在尝试删除它们。然后我转到下一个项目。

您可以将每个与条件不匹配的元素复制到第二个列表中:

result = []
for item in a:
    if condition is False:
        result.append(item)
a = result

或者,您可以使用filter或列表推导并将结果分配回a

a = filter(lambda item:... , a)

或者

a = [item for item in a if ...]

where...代表您需要检查的条件。

于 2012-05-19T13:32:42.277 回答
86

遍历列表的副本:

>>> a = ["a", "b", "c", "d", "e"]
>>> for item in a[:]:
    print(item)
    if item == "b":
        a.remove(item)

a
b
c
d
e
>>> print(a)
['a', 'c', 'd', 'e']
于 2012-05-19T13:37:06.020 回答
25

正如其他答案所说,最好的方法是创建一个新列表 - 迭代一个副本,或者构建一个仅包含您想要的元素的列表并将其分配回同一个变量。这些之间的区别取决于您的用例,因为它们会以不同的方式影响原始列表的其他变量(或者,更确切地说,第一个会影响它们,而第二个不会)。

如果由于某种原因无法选择副本,则您确实有另一个选择,该选择依赖于对为什么修改您正在迭代的列表的理解中断。列表迭代通过跟踪索引来工作,每次在循环中递增它,直到它掉出列表的末尾。因此,如果您在当前索引处(或之前)删除,则从该点到结尾的所有内容都会向左移动一个位置。但是迭代器不知道这一点,并且有效地跳过了下一个元素,因为它现在位于当前索引而不是下一个。但是,删除当前索引之后的内容不会影响内容。

这意味着如果您将列表迭代回前面,如果您删除当前索引处的项目,则它右侧的所有内容都会向左移动 - 但这并不重要,因为您已经处理了右侧的所有元素当前位置,并且您正在向左移动 - 左侧的下一个元素不受更改的影响,因此迭代器为您提供了您期望的元素。

TL;博士:

>>> a = list(range(5))
>>> for b in reversed(a):
    if b == 3:
        a.remove(b)
>>> a
[0, 1, 2, 4]

但是,就使代码易于阅读而言,制作副本通常更好。为了完整起见,我只提到这种可能性。

于 2012-05-19T13:59:07.443 回答
5
import copy

a = ["a", "b", "c", "d", "e"]

b = copy.copy(a)

for item in a:
    print(item)
    b.remove(item)
a = copy.copy(b)

作品:为避免更改您正在迭代的列表,您制作一个副本a,对其进行迭代并从中删除项目b。然后您将b(更改后的副本)复制回a.

于 2014-07-17T08:11:42.453 回答
4

如何创建一个新列表并将您想要的元素添加到该新列表中。遍历列表时不能删除元素

于 2012-05-19T13:33:47.300 回答
2

回答这个问题可能有点晚了,但我刚刚找到了这个线程,并且我之前已经为它创建了自己的代码......

    list = [1,2,3,4,5]
    deleteList = []
    processNo = 0
    for item in list:
        if condition:
            print(item)
            deleteList.insert(0, processNo)
        processNo += 1

    if len(deleteList) > 0:
        for item in deleteList:
            del list[item]

这可能是一个很长的路要走,但似乎运作良好。我创建了第二个列表,其中仅包含与要删除的列表项相关的数字。请注意,“插入”在位置 0 处插入列表项编号并推动其余部分,因此在删除项目时,列表将从最高编号删除回最低编号,因此列表保持顺序。

于 2015-03-28T05:39:56.910 回答