我有一个列表。
a = ["a", "b", "c", "d", "e"]
我想在一个for循环中删除这个列表中的元素,就像下面这样:
for item in a:
print(item)
a.remove(item)
但是它不起作用。我该怎么办?
使用for
循环迭代列表时,不允许从列表中删除元素。
重写代码的最佳方式取决于您要完成什么任务。
例如,您的代码等效于:
for item in a:
print(item)
a[:] = []
或者,您可以使用 while
循环:
while a:
print(a.pop())
我试图根据条件删除项目,然后转到下一个项目。
您可以将不符合条件的每个元素复制到第二个列表中:
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 ...]
...
代表您需要检查的条件。
.pop(0)
非常低效!它的时间复杂度为O(N)。只需使用pop()
,其时间复杂度为O(1)。 - crypdick遍历列表的副本:
>>> 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']
item
从“b”跳到“d”,因此如果我们想要删除“b”或“c”,那么它将失败。快速解释:https://gist.github.com/alexlouden/9f1ab4354d1c68ae4c1c94126ac51a20 - Alex L正如其他答案所述,最好的方法涉及创建一个新列表-要么迭代一个副本,要么构造仅包含所需元素的列表,并将其赋回给同一变量。这两种方法的区别取决于您的用例,因为它们对原始列表的其他变量产生不同的影响(或者更确切地说,第一种会影响它们,而第二种则不会)。
如果由于某种原因不能使用副本,则还有一种依赖于理解为什么修改正在迭代的列表会出问题的选项。列表迭代通过保持索引跟踪来工作,在每次循环中将其递增,直到它从列表末尾掉落。因此,如果您在当前索引处(或之前)删除,从该点到结尾的所有内容都会向左移动一个位置。但是迭代器并不知道这一点,实际上跳过下一个元素,因为它现在位于当前索引而不是下一个索引。但是,删除在当前索引之后的元素不会影响事情。
这意味着,如果您反向迭代列表,如果在当前索引处删除一个项目,则其右侧的所有内容都会向左移动-但这并不重要,因为您已经处理了当前位置右侧的所有元素,并且您正在向左移动-左侧的下一个元素不受更改的影响,因此迭代器会给您期望的元素。
总之:
>>> a = list(range(5))
>>> for b in reversed(a):
if b == 3:
a.remove(b)
>>> a
[0, 1, 2, 4]
然而,通常复制代码更有利于使代码易读。我只是提出这种可能性以保持完整性。
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
中。
创建一个新的列表,并向该列表添加所需元素。在遍历列表时不能删除元素。
可能有点晚回答,但我刚发现这个线程,之前我已经为此创建了自己的代码...
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]