正如您所发现的,尝试从您正在迭代的列表中删除元素可能不会达到您的预期。 Ashwani Agarwal 的回答说明了它失败的原因,其他答案显示了可用于正确执行删除的各种技术。当您有一个无法复制的非常大的列表时,另一种有用的技术是反向迭代它:
my_list = ['a', 'b', 'c', 'a', 'b', 'c', 'a']
for element in reversed(my_list):
if 'a' not in element:
my_list.remove(element)
print(element, my_list)
print('Final:', my_list)
my_list = ['a', 'b', 'c', 'a', 'b', 'c', 'a']
for element in reversed(my_list):
if 'a' in element:
my_list.remove(element)
print(my_list)
print('Final:', my_list)
输出
c ['a', 'b', 'a', 'b', 'c', 'a']
c ['a', 'b', 'a', 'b', 'a']
b ['a', 'a', 'b', 'a']
b ['a', 'a', 'a']
Final: ['a', 'a', 'a']
['b', 'c', 'a', 'b', 'c', 'a']
['b', 'c', 'b', 'c', 'a']
['b', 'c', 'b', 'c']
Final: ['b', 'c', 'b', 'c']
此代码使用reversed() 函数,该函数返回一个迭代器,覆盖您传递给它的可迭代对象;它不会复制可迭代的。
我应该提到,这种技术比其他答案中给出的过滤方法效率低。这是因为my_list.remove(element) 的每次调用都必须扫描my_list 直到找到匹配的元素,所以它的复杂度为O(n**2),其中n 是列表中元素的数量;过滤算法的复杂度为 O(n)。因此,正如我之前所说,这种方法仅在列表太大以至于您无法负担 RAM 来创建新列表的情况下才有用。
关于您问题中的代码,我需要提及的另一件事是:当您应该使用普通的 for 循环时,您正在使用列表推导来循环列表。 list.remove() 返回None,因此您的代码不必要地创建了一个充满Nones 的列表,然后将该列表丢弃。一般规则是:不要将列表推导纯粹用于您在其中调用的函数的副作用。