我有一个清单L.
我可以删除元素i:
del L[i]
但是如果我有一组不连续的索引要删除呢?
I=set([i1, i2, i3,...])
这样做的:
for i in I:
del L[i]
不行。
有什么想法吗?
答案 0 :(得分:31)
Eine Minuten bitte,Ich hap eine kleine Problemo avec diese Religione。 - Eddie Izzard(做他的印象 马丁·路德(Martin Luther))
通过对列表进行反向迭代来删除以保留迭代器 是解决此问题的常用方法。但另一种解决方案是将其改为另一个问题。不是使用某些条件从列表中删除项目(在您的情况下,索引存在于要删除的索引列表中),而是创建一个新的列表,而不会删除违规项目。
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]
在大多数情况下,我将有关“如何从列表中删除我不想要的项目”的任何问题转变为“如何创建仅包含我想要的项目的新列表”。
EDITED:根据Alex Martelli对this question的回答,将“L = ......”更改为“L [:] = ...”。
答案 1 :(得分:9)
for i in I:
del L[i]
将无效,因为(取决于顺序)您可能使迭代器无效 - 这通常会显示为您要删除的一些项目保留在列表中。
按照索引的相反顺序从列表中删除项目总是安全的。最简单的方法是使用sorted():
for i in sorted(I, reverse=True):
del L[i]
答案 2 :(得分: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编写的编译代码。
答案 3 :(得分:1)
如果原始列表数据可以安全地转换为集合(即所有唯一值并且不需要维护顺序),您还可以使用集合操作:
Lset = set(L)
newset = Lset.difference(I)
你也可以用Bag / Multiset做点什么,虽然它可能不值得努力。 Paul McGuire的第二个listcomp解决方案对于大多数情况来说当然是最好的。
答案 4 :(得分:0)
L = [ item for item in L if L.index(item) not in I ]