我有一个列表L。
我可以通过以下方式删除元素i:
del L[i]
但如果我有一组非连续索引需要删除怎么办?
I=set([i1, i2, i3,...])
进行中:
for i in I:
del L[i]
不会起作用。
有任何想法吗?
请等一分钟,我有一个小问题与这个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]
大部分情况下,我会将任何关于“如何从列表中删除不需要的项”的问题转化为“如何创建一个只包含我想要的项的新列表”的问题。item.isValid()
得到了 +1。顺便说一句,如果您已经有了一组索引,则不必像第一个代码解决方案中那样使用 enumerate 来创建元组。我更喜欢 [ L[i] for i in xrange(len(L)) if i not in I ]
。要完整地了解如何这样做,请参见 https://dev59.com/AHRB5IYBdhLWcg3w1Kle#20589125。在该链接中,我还展示了一个相关的解决方案,如果您有一个要删除的值列表,而不是索引。 - ToolmakerStevefor i in I:
del L[i]
这样做是不行的,因为(根据顺序)你可能会使迭代器无效 - 这通常表现为你打算删除的某些项仍然留在列表中。
以它们的索引逆序从列表中删除项目总是安全的。最简单的方法是使用sorted():
for i in sorted(I, reverse=True):
del L[i]
O(n^2)
(实际上是O(n*m)
,我想,取决于每个列表的大小),因为每个删除都必须复制该点之后列表的整个内容。 Paul的解决方案可能更像O(m log n),而且同样容易。 - Glenn Maynardnumpy.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']
Lset = set(L)
newset = Lset.difference(I)
你也可以尝试使用 Bag/Multiset 进行一些操作,但这可能并不值得努力。对于大多数情况来说,Paul McGuire 的第二个列表推导解决方案肯定是最好的。
L = [ item for item in L if L.index(item) not in I ]