如何在Python中删除for循环中的列表元素?

alw*_*btc 63 python list

我有一份清单

a = ["a", "b", "c", "d", "e"]
Run Code Online (Sandbox Code Playgroud)

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

for item in a:
    print item
    a.remove(item)
Run Code Online (Sandbox Code Playgroud)

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

NPE*_*NPE 102

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

重写代码的最佳方法取决于您正在尝试做什么.

例如,您的代码相当于:

for item in a:
  print item
a[:] = []
Run Code Online (Sandbox Code Playgroud)

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

while a:
  print a.pop(0)
Run Code Online (Sandbox Code Playgroud)

我试图删除符合条件的项目.然后我去下一个项目.

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

result = []
for item in a:
  if condition is False:
    result.append(item)
a = result
Run Code Online (Sandbox Code Playgroud)

或者,您可以使用filter或列表理解并将结果分配回a:

a = filter(lambda item:... , a)
Run Code Online (Sandbox Code Playgroud)

要么

a = [item for item in a if ...]
Run Code Online (Sandbox Code Playgroud)

在哪里...代表您需要检查的条件.

  • "你不被允许" - 确定你是.Python不会抱怨你,它只是给人们可能期望的一点点(读取:完全)不同的结果. (8认同)
  • 问题是python保留了一个内部计数器来记住当前元素,当列表从迭代器下面更改时,它会引用意外内容。(但是在删除时从头到尾迭代可能会按预期工作吗?) (4认同)
  • 为什么?有人可以指出为什么会这样的描述?每次迭代都会重新评估该列表,对吧?所以有什么问题? (3认同)
  • 使用 `.pop(0)` 效率非常低!它的时间复杂度为O(N)。只需使用时间复杂度为 O(1) 的 pop() 即可。 (2认同)

Ale*_*x L 53

迭代列表的副本:

>>> 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']
Run Code Online (Sandbox Code Playgroud)

  • @NPE我想这取决于你期望发生的事情.如果您希望代码删除列表中的所有"b"实例,那么它不应该破坏为[list.remove](https://docs.python.org/2/tutorial/datastructures.html#more- on-lists)只删除一个项目. (3认同)
  • 这个问题和 OP 的方法的一个问题是,如果有多个元素比较相等,它们可能会崩溃。 (2认同)
  • 一个大列表的内存问题? (2认同)

lvc*_*lvc 18

正如其他答案所述,执行此操作的最佳方法是创建一个新列表 - 迭代副本,或构建仅包含所需元素的列表,并将其分配回同一变量.它们之间的区别取决于您的用例,因为它们会不同地影响原始列表的其他变量(或者,第一个影响它们,第二个不影响它们).

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

这意味着如果你将列表重复到前面,如果你删除当前索引处的项目,那么它的所有内容都向右移动 - 但这没关系,因为你已经处理了右边的所有元素当前位置,并且您向左移动 - 左侧的下一个元素不受更改的影响,因此迭代器为您提供您期望的元素.

TL; DR:

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

但是,在使代码易于阅读方面,制作副本通常会更好.为了完整起见,我只提到了这种可能性.


小智 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)
Run Code Online (Sandbox Code Playgroud)

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