删除列表中的多个元素(python)

17 投票
5 回答
41422 浏览
提问于 2025-04-15 14:27

我有一个列表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[:] = ...",参考了这个问题

撰写回答