Python中通过索引的简洁方法删除列表元素

5

我有一个字符列表和一个索引列表

myList = ['a','b','c','d']
toRemove = [0,2]

我希望能以一次操作完成此事,与IT技术有关。

myList = ['b','d']

我能做这个,但有没有更快的方法?

toRemove.reverse()
for i in toRemove:
    myList.pop(i)

2
你提供的示例实现是不正确的,或者可能是你的规范有误。该算法会移除索引为0的项,然后移除由于移除操作而移到索引2的项(也就是'd')。 - user395760
我使用了 toRemove.reverse,这样第一个要删除的元素就在索引2上,然后我再删除索引0上的元素。这只有在 toRemove 列表已排序时才有效。 - Youcha
5个回答

5

简要回答

>>> myList = ['a','b','c','d']
>>> toRemove = [0,2]
>>> 
>>> [v for i, v in enumerate(myList) if i not in toRemove]
['b', 'd']
>>> 

2
toRemove变成一个集合,这实际上是一个非常好的算法。它的时间复杂度为O(m),而不是O(n * m),其中n = len(toRemove); m = len(myList),因为它在每次删除一个项目时不会重复复制数组的一半。 - user395760
toRemove设置为set可能是个好主意,但这取决于toRemovemyList的长度是否会有所改善。我最初没有写那个,因为我想要简洁! - Nick Craig-Wood

5
您可以像其他答案建议的那样使用列表推导式,但为了使其真正更快,我建议使用set来存储您想要删除的索引集合。
>>> myList = ['a','b','c','d']
>>> toRemove = set([0,2])
>>> [x for i,x in enumerate(myList) if i not in toRemove]
['b', 'd']

将myList中的每个元素与toRemove中的每个元素进行比较是O(n*m)(其中n是myList的长度,m是toRemove的长度)。如果使用set,则会员检查为O(1),因此整个过程变为O(n)。但请记住,除非toRemove非常大(例如超过千个),否则速度差异不会很明显。


4

如果您愿意的话,您可以使用numpy

import numpy as np

myList = ['a','b','c','d']
toRemove = [0,2]

new_list = np.delete(myList, toRemove)

结果:

>>> new_list
array(['b', 'd'], 
      dtype='|S1')

请注意,new_list 是一个 numpyarray

2
你不觉得Numpy对于一个简单的“删除数组”问题有点过头了吗? - Name McChange
1
也许原帖作者已经在使用 numpy,而且所涉及的列表有数百万个元素?如果是这样,那么这可能是最快的答案。 - Nick Craig-Wood
@SuperDisk,我认为使用numpy的方式非常方便,也很有用。当然,如果没有numpy,这个任务也很容易完成,但是提到numpy选项还是值得一提的。 - Akavall
我现在有了numpy,这正是我所需要的。谢谢。 - Youcha
1
@Youcha 不是针对你,但下次最好说明你使用的模块 :) - Name McChange

1

一行代码:

>>>[myList[x] for x in range(len(myList)) if not x in [0,2]]
['b', 'd']

0
你可以编写一个函数来为你完成它。
def removethese(list, *args):
    for arg in args:
        del list[arg]

然后执行

mylist = ['a', 'b', 'c', 'd', 'e']
removethese(mylist, 0, 1, 4)

我的列表现在是 ['c', 'd']


这个实现和 OP 的一样不正确(再次假设规范是正确的)。 - user395760

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接