从列表中删除多个元素

142 python list

是否可以同时从列表中删除多个元素?如果我想删除索引0和2处的元素,并尝试类似del somelist [0],然后是del somelist [2],则第二个语句实际上会删除somelist [3].

我想我总是可以先删除编号较高的元素,但我希望有更好的方法.

tgl*_*ria 151

出于某种原因,我不喜欢这里的任何答案.是的,它们可以工作,但严格来说,大多数都没有删除列表中的元素,是吗?(但制作副本,然后用编辑后的副本替换原来的副本).

为什么不先删除更高的索引?

是否有一个原因?我会这样做:

for i in sorted(indices, reverse=True):
    del somelist[i]
Run Code Online (Sandbox Code Playgroud)

如果你真的不想向后删除项目,那么我想你应该只是减去索引值,这些值大于上次删除的索引(因为你有不同的列表所以不能真正使用相同的索引)或者使用列表的副本(不是'删除',而是用编辑后的副本替换原件).

我在这里遗漏了什么,有什么理由不以相反的顺序删除吗?

  • 有两个原因。(a) 对于列表,平均而言(假设随机索引),时间复杂度将高于“制作副本”方法(使用一组索引),因为某些元素需要多次向前移动。(b) 至少对我来说,它很难阅读,因为有一个排序函数与任何实际的程序逻辑都不对应,并且仅出于技术原因而存在。尽管现在我已经完全理解了其中的逻辑,但我仍然_感觉_阅读起来很困难。 (8认同)
  • 我知道这是差不多一年前的答案,但我想回应@portforwardpodcast,你的答案非常好,仍然有用,而且埋得太远了.感谢并感谢您提供有用的评论. (5认同)

Gre*_*ill 102

如果您要删除多个不相邻的项目,那么您所描述的是最好的方式(是的,请务必从最高的索引开始).

如果您的项目是相邻的,则可以使用切片分配语法:

a[2:10] = []
Run Code Online (Sandbox Code Playgroud)

  • 你也可以说'del a [2:10]`具有相同的效果. (82认同)
  • @sth有趣的是,del比分配快一点. (7认同)

Sil*_*ost 95

可能不是解决此问题的最佳解决方案:

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

  • 这根本不是从某个列表中删除项目,而是创建一个全新的列表.如果有任何东西持有对原始列表的引用,它仍将包含其中的所有项目. (12认同)
  • 我选择元组索引的原因只是记录的简单性.对于set()赋予O(n)这将是一个完美的工作 (4认同)
  • 改变主意。通过给出枚举结果更具描述性的名称,这种方法很容易阅读。如果添加括号,它也会对我有帮助。即:“[如果 i 不在 set(indices) 中,则 enumerate(lst) 中 (i, value) 的值]”。 (3认同)
  • 几乎,只有删除整个列表.它将是len(指数)*len(somelist).它还会创建一个副本,可能需要也可能不需要 (2认同)
  • 抬头不是线性的 (2认同)
  • @SilentGhost没有必要进行枚举.怎么样:`somelist = [lst [i] for i in xrange(len(lst))如果我不在set(indices)中``? (2认同)

bob*_*nce 18

作为Greg答案的专长,您甚至可以使用扩展切片语法.例如.如果要删除项目0和2:

>>> a= [0, 1, 2, 3, 4]
>>> del a[0:3:2]
>>> a
[1, 3, 4]
Run Code Online (Sandbox Code Playgroud)

当然,这并不涵盖任何选择,但它肯定可以用于删除任何两个项目.


Nik*_*iah 17

作为一个功能:

def multi_delete(list_, *args):
    indexes = sorted(list(args), reverse=True)
    for index in indexes:
        del list_[index]
    return list_
Run Code Online (Sandbox Code Playgroud)

运行n log(n)时间,这应该是它最快的正确解决方案.

  • `n log n`?真的吗?我不认为`del list[index]` 是 O(1)。 (4认同)

phi*_*ilE 17

您可以使用numpy.delete如下:

import numpy as np
a = ['a', 'l', 3.14, 42, 'u']
I = [0, 2]
np.delete(a, I).tolist()
# Returns: ['l', '42', 'u']
Run Code Online (Sandbox Code Playgroud)

如果你不介意最后得到一个numpy数组,你可以省略.tolist().您应该看到一些非常重要的速度改进,使其成为一个更具可扩展性的解决方案.我没有对它进行基准测试,但是numpy操作是用C或Fortran编写的编译代码.


Ric*_*eur 11

那么,你基本上想要一次删除多个元素?在这种情况下,要删除的下一个元素的位置将被偏移,但之前删除了许多元素.

我们的目标是删除预先计算为索引1,4和7的所有元音.请注意,重要的是to_delete索引按升序排列,否则它将无效.

to_delete = [1, 4, 7]
target = list("hello world")
for offset, index in enumerate(to_delete):
  index -= offset
  del target[index]
Run Code Online (Sandbox Code Playgroud)

如果您想以任何顺序删除元素,那将会更复杂.IMO,排序to_delete可能比确定何时应该或不应该减去更容易index.


小智 6

我是Python的初学者,目前我的编程简直粗糙,但我的解决方案是使用我在早期教程中学到的基本命令的组合:

SomeList = [1,2,3,4,5,6,7,8,10]
Rem = [0,5,7]

for i in Rem:
    SomeList[i]='!' # mark for deletion

for i in range(0,SomeList.count('!')):
    SomeList.remove('!') # remove
print SomeList
Run Code Online (Sandbox Code Playgroud)

显然,由于必须选择"删除标记"字符,这有其局限性.

至于列表大小的性能,我确信我的解决方案是次优的.然而,它很简单,我希望吸引其他初学者,并且将在SomeList具有众所周知格式的简单情况下工作,例如,总是数字......

  • 在python中,很少将变量名称大写. (5认同)
  • 而不是使用“!” 作为您的特殊字符,请使用 None。这使每个字符都有效并释放您的可能性 (4认同)

Too*_*eve 5

这是一个替代方案,它不使用enumerate()来创建元组(如在SilentGhost的原始答案中).

这对我来说似乎更具可读性.(如果我习惯使用枚举,也许我会有不同的感受.)CAVEAT:我没有测试过两种方法的表现.

# Returns a new list. "lst" is not modified.
def delete_by_indices(lst, indices):
    indices_as_set = set(indices)
    return [ lst[i] for i in xrange(len(lst)) if i not in indices_as_set ]
Run Code Online (Sandbox Code Playgroud)

注意:Python 2.7语法.对于Python 3,xrange=> range.

用法:

lst = [ 11*x for x in xrange(10) ]
somelist = delete_by_indices( lst, [0, 4, 5])
Run Code Online (Sandbox Code Playgroud)

somelist:

[11, 22, 33, 66, 77, 88, 99]
Run Code Online (Sandbox Code Playgroud)

---奖金---

从列表中删除多个值.也就是说,我们有我们想要删除的值:

# Returns a new list. "lst" is not modified.
def delete__by_values(lst, values):
    values_as_set = set(values)
    return [ x for x in lst if x not in values_as_set ]
Run Code Online (Sandbox Code Playgroud)

用法:

somelist = delete__by_values( lst, [0, 44, 55] )
Run Code Online (Sandbox Code Playgroud)

somelist:

[11, 22, 33, 66, 77, 88, 99]
Run Code Online (Sandbox Code Playgroud)

这与以前的答案相同,但这次我们提供了要删除的VALUES [0, 44, 55].


Meo*_*eow 5

使用列表索引值的替代列表理解方法:

stuff = ['a', 'b', 'c', 'd', 'e', 'f', 'woof']
index = [0, 3, 6]
new = [i for i in stuff if stuff.index(i) not in index]
Run Code Online (Sandbox Code Playgroud)

这将返回:

['b', 'c', 'e', 'f']
Run Code Online (Sandbox Code Playgroud)

  • 很好的答案,但是将索引列表命名为“index”会产生误导,因为在列表迭代器中使用了方法“index()” (2认同)