如何在 Python 的 for 循环中删除列表元素? [复制]
Posted
技术标签:
【中文标题】如何在 Python 的 for 循环中删除列表元素? [复制]【英文标题】:How to remove list elements in a for loop in Python? [duplicate] 【发布时间】:2012-05-26 19:02:02 【问题描述】:我有一个清单
a = ["a", "b", "c", "d", "e"]
我想在下面的 for 循环中删除此列表中的元素:
for item in a:
print(item)
a.remove(item)
但它不起作用。我能做什么?
【问题讨论】:
为什么要同时删除?只需遍历然后删除整个列表。另外,您真的需要打印每个项目吗? 但是当我遍历循环时,我依赖于列表中的项目。如果它符合条件,我必须立即摆脱它 【参考方案1】:在使用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 ...]
其中...
代表您需要检查的条件。
【讨论】:
我正在尝试删除符合条件的项目。然后我转到下一项。 “你不被允许”——当然可以。 Python 不会抱怨你,它只是给出了与人们期望的稍微(阅读:完全)不同的结果。 为什么?有人可以指出为什么会这样吗?该列表在每次迭代中都会重新评估,对吗?那么有什么问题呢? 问题是python保留了一个内部计数器来记住当前的elelement,当列表从迭代器下发生变化时,它将引用一些意想不到的东西。 (但在删除时从后向前迭代可能会按预期工作?) 使用.pop(0)
效率非常低!它的时间复杂度为 O(N)。只需使用时间复杂度 O(1) 的pop()
。【参考方案2】:
遍历列表的副本:
>>> 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']
【讨论】:
这个和 OP 方法的一个问题是,如果有多个比较相等的元素,它们可能会崩溃。 太棒了!这个对我有用! @NPE 我想这取决于你期望发生什么。如果您希望代码删除列表中的所有“b”实例,那么它不应该中断,因为list.remove 只删除了一项。 大列表的内存问题? @aggregate1166877 好问题!在这种情况下,如果我们不遍历副本,那么删除“b”将使item
从b
跳到d
- 所以如果我们想删除“b”或“c”,那么它会失败。快速解释:gist.github.com/alexlouden/9f1ab4354d1c68ae4c1c94126ac51a20【参考方案3】:
正如其他答案所说,最好的方法是创建一个新列表 - 遍历副本,或者构建一个仅包含您想要的元素的列表并将其分配回同一个变量。这些之间的区别取决于您的用例,因为它们会以不同的方式影响原始列表的其他变量(或者,更确切地说,第一个会影响它们,而第二个不会)。
如果由于某种原因无法选择副本,您确实有另一个选择,该选择依赖于理解为什么修改您正在迭代的列表会中断。列表迭代通过跟踪索引来工作,每次在循环中递增它,直到它掉出列表的末尾。因此,如果您在当前索引处(或之前)删除,则从该点到结尾的所有内容都会向左移动一个位置。但是迭代器不知道这一点,并且有效地跳过了下一个元素,因为它现在位于 current 索引而不是下一个。但是,删除当前索引 之后的内容不会影响任何内容。
这意味着,如果您将列表迭代到前面,如果您删除当前索引处的项目,则它右侧的所有内容都会向左移动 - 但这并不重要,因为您已经处理了所有要当前位置的右侧,并且您正在向左移动 - 左侧的下一个元素不受更改的影响,因此迭代器为您提供了您期望的元素。
TL;DR:
>>> a = list(range(5))
>>> for b in reversed(a):
if b == 3:
a.remove(b)
>>> a
[0, 1, 2, 4]
但是,就使代码易于阅读而言,制作副本通常更好。为了完整起见,我只提到这种可能性。
【讨论】:
【参考方案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
。
【讨论】:
等等,所以 .remove(...) 可以从“b”中删除实例,即使从技术上讲,传递的实例是“a”的实例?【参考方案5】:如何创建一个新列表并将您想要的元素添加到该新列表中。遍历列表时不能删除元素
【讨论】:
【参考方案6】:回答这个问题可能有点晚了,但我刚刚找到了这个帖子,并且我之前已经为它创建了自己的代码......
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 处插入列表项编号并将其余部分推入,因此在删除项时,列表将从最高编号删除回最低编号,因此列表保持顺序。
【讨论】:
以上是关于如何在 Python 的 for 循环中删除列表元素? [复制]的主要内容,如果未能解决你的问题,请参考以下文章