删除列表中的多个元素(python)
我有一个列表L。
我可以通过以下方式删除第i个元素:
del L[i]
但是如果我有一组不连续的索引想要删除呢?
I=set([i1, i2, i3,...])
这样做:
for i in I:
del L[i]
是行不通的。
有没有什么好主意?
5 个回答
4
你可以这样使用 numpy.delete
:
import numpy as np
a = ['a', 'l', 3.14, 42, 'u']
I = [1, 3, 4]
np.delete(a, I).tolist()
# Returns: ['a', '3.14']
如果你不介意最后得到的是一个 numpy
数组,可以省略 .tolist()
。这样做会让速度明显提升,变得更高效。我没有做过具体的性能测试,但 numpy
的操作是用 C 或 Fortran 这些语言写的编译代码,所以速度会很快。
9
for i in I:
del L[i]
这样做是行不通的,因为(根据顺序的不同)你可能会让迭代器失效——这通常会导致你想删除的某些项目仍然留在列表中。
从列表中删除项目时,按照索引的反向顺序删除总是安全的。最简单的方法是使用 sorted() 函数:
for i in sorted(I, reverse=True):
del L[i]
32
等一下,我有一个小问题和这个宗教有关。 -- Eddie Izzard(模仿马丁·路德)
通过反向遍历列表来删除元素,以保持迭代器的完整性,这是一种常见的解决方案。不过,还有另一种方法,就是把这个问题换个角度来看。与其根据某些标准(在你的情况下,是索引是否在待删除索引列表中)从列表中删除项目,不如创建一个新列表,把那些不想要的项目排除在外。
L[:] = [ item for i,item in enumerate(L) if i not in I ]
说到这一点,你最开始是从哪里得到列表 I
中的索引的呢?你可以把获取要删除的索引和构建新列表的逻辑结合起来。假设这是一个对象列表,而你只想保留那些通过 isValid
测试的对象:
L[:] = [ item for item in L if item.isValid() ]
这样做比:
I = set()
for i in range(len(L)):
if not L[i].isValid():
I.add(i)
for i in sorted(I, reverse=True):
del L[i]
大多数情况下,我会把任何关于“如何从列表中删除我不想要的项目”的问题,转变为“如何创建一个只包含我想要的项目的新列表”。
编辑:根据 Alex Martelli 的回答,把 "L = ..." 改成 "L[:] = ...",参考了这个问题。