如何同时从列表中删除多个索引?

use*_*497 97 python

说我在这里有这个列表:

list = [a, b, c, d, e, f, g]
Run Code Online (Sandbox Code Playgroud)

我如何删除说索引2, 3, 4,5同时?

pop不接受多个值.我怎么做呢?

Ned*_*der 174

您需要在循环中执行此操作,没有内置操作一次删除多个索引.

您的示例实际上是一个连续的索引序列,因此您可以这样做:

del my_list[2:6]
Run Code Online (Sandbox Code Playgroud)

从2开始删除切片,在6之前结束.

从您的问题中不清楚一般是否需要删除任意索引集合,或者它是否始终是连续的序列.

如果您有任意索引集合,那么:

indexes = [2, 3, 5]
for index in sorted(indexes, reverse=True):
    del my_list[index]
Run Code Online (Sandbox Code Playgroud)

请注意,您需要以相反的顺序删除它们,以免丢弃后续索引.

  • 向下循环指数.天才!当我走的时候,我在这里梦想着一些减少指数的荒谬局面,当时这更加优雅! (30认同)
  • +1如果不是`del my_list [index]`我们使用`my_list.pop(index)`,这会有什么不同?这有关系吗?在效率或语义方面? (4认同)
  • @Levon 我认为主要区别在于您删除的 [pop 返回值](/sf/answers/399931241/)。由于我们不需要要删除的值,因此在这种情况下我们可能应该使用 `del`,尽管两者都可以。 (3认同)
  • @kitensei它确实重新索引,但因为首先以相反的顺序对索引进行排序,所以我们从列表的右端删除,所以在删除元素之前我们永远不会重新索引它。 (2认同)

Igo*_*bin 30

remove_indices = [1,2,3]
somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]
Run Code Online (Sandbox Code Playgroud)

例:

In [9]: remove_indices = [1,2,3]

In [10]: somelist = range(10)

In [11]: somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]

In [12]: somelist
Out[12]: [0, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

  • 正如 @C.Yduqoli 下面指出的,这是最有效的解决方案(我们不需要不断重建列表),但您必须首先将 `remove_indices` 转换为 `set`! (6认同)

And*_*ris 16

对于不同的方式没有太多关于性能的提示,所以我在所有3种通常不同的方法中执行了从50000中删除5000个项目的测试,对我来说numpy是赢家(如果你有适合numpy的元素):

  • 枚举列表理解为7.5秒[另一台PC为4.5秒]
  • 按相反顺序删除项目0.08秒[0.017(!)sec]
  • numpy.delete为0.00秒[0.006秒]

这是我定时的代码(如果直接在numpy数组上运行,可以删除第三个函数从/到列表的转换):

import time
import numpy as np
import random

def del_list_indexes(l, id_to_del):
    somelist = [i for j, i in enumerate(l) if j not in id_to_del]
    return somelist

def del_list_inplace(l, id_to_del):
    for i in sorted(id_to_del, reverse=True):
        del(l[i])

def del_list_numpy(l, id_to_del):
    arr = np.array(l, dtype='int32')
    return list(np.delete(arr, id_to_del))

l = range(50000)
random.shuffle(l)
remove_id = random.sample(range(len(l)), 5000) # 10% ==> 5000

# ...
Run Code Online (Sandbox Code Playgroud)

  • 如果先将 id_to_del 转换为集合,del_list_indexes 应该会快得多。 (3认同)
  • @C.Yduqoli 如果使用“set”作为“enumerate”**,我得到的时间是:“enumerate”= 0.0041,“del”= 0.035,“numpy”= 0.0079,它按照预期枚举为最快。 (2认同)

Ant*_*ony 12

如果它们是连续的,你就可以做到

x[2:6] = []
Run Code Online (Sandbox Code Playgroud)

如果要删除不连续的索引,则有点棘手.

x = [v for i,v in enumerate(x) if i not in frozenset((2,3,4,5))] 
Run Code Online (Sandbox Code Playgroud)


fra*_*xel 9

如果你可以使用numpy,那么你可以删除多个索引:

>>> import numpy as np
>>> a = np.arange(10)
>>> np.delete(a,(1,3,5))
array([0, 2, 4, 6, 7, 8, 9])
Run Code Online (Sandbox Code Playgroud)

如果您使用,np.r_您可以将切片与单个索引组合:

>>> np.delete(a,(np.r_[0:5,7,9]))
array([5, 6, 8])
Run Code Online (Sandbox Code Playgroud)

但是,删除不是in place,所以你必须分配给它.


sre*_*til 5

lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
lst = lst[0:2] + lst[6:]
Run Code Online (Sandbox Code Playgroud)

这是一个单步操作。它不使用循环,因此执行速度很快。它使用列表切片。

  • 想知道为什么 1460 天和 23410 次浏览,没有想出这个简单的解决方案。这有点令人沮丧。 (2认同)