有没有可能同时从列表中删除多个元素?如果我想删除索引为0和2的元素,并尝试类似于del somelist [0]
然后跟着del somelist [2]
,第二条语句实际上会删除somelist[3]
。
我猜我可以总是先删除较高编号的元素,但我希望有更好的方法。
由于某些原因,我不喜欢这里的任何答案。 是的,它们起作用,但严格来说,它们大多数并没有删除列表中的元素,对吧?(而是制作一个副本,然后用编辑过的副本替换原来的副本)。
为什么不首先删除较高的索引呢?
这样做有什么原因吗? 我只会这样做:
for i in sorted(indices, reverse=True):
del somelist[i]
如果你真的不想向后删除项目,那么我猜你应该只减少索引值,这些索引值大于最后删除的索引(不能使用相同的索引,因为你有一个不同的列表),或者使用列表的副本(这不是“删除”,而是用编辑过的副本替换原始列表)。
我在这里错过了什么,有任何不删除反向排序的原因吗?
somelist.pop(i)
而不是 del
。 - user5359531您可以使用 enumerate
并删除其索引与要删除的索引匹配的值:
indices = 0, 2
somelist = [i for j, i in enumerate(somelist) if j not in indices]
somelist = [ lst[i] for i in xrange(len(lst)) if i not in set(indices) ]
? - ToolmakerSteve[ value for (i, value) in enumerate(lst) if i not in set(indices) ]
。 - ToolmakerSteve如果你要删除多个不相邻的项目,那么你所描述的方法是最好的(是的,请确保从最高索引开始)。
如果你的项目是相邻的,你可以使用切片赋值语法:
a[2:10] = []
del a[2:10]
达到相同的效果。 - sthnumpy.delete
:import numpy as np
a = ['a', 'l', 3.14, 42, 'u']
I = [0, 2]
np.delete(a, I).tolist()
# Returns: ['l', '42', 'u']
如果您不介意最终得到一个numpy
数组,那么可以省略.tolist()
。您应该会看到一些相当大的速度提升,使这成为一种更具可扩展性的解决方案。虽然我没有进行基准测试,但numpy
操作是用C或Fortran编写的编译代码。
作为 Greg 回答的一个特例,你甚至可以使用扩展切片语法。例如,如果你想删除项 0 和 2:
>>> a= [0, 1, 2, 3, 4]
>>> del a[0:3:2]
>>> a
[1, 3, 4]
当然,这并不能涵盖任意选择,但对于删除任意两个项目肯定可行。
作为一个函数:
def multi_delete(list_, *args):
indexes = sorted(list(args), reverse=True)
for index in indexes:
del list_[index]
return list_
运行时间为n log(n),这应该是迄今为止最快的正确解决方案。
list(args)
放入 sorted()
中,list()
包装器不再必要,正如 SilentGhost 的回复评论所述。使用元组输入进行测试和验证。已提交为编辑。 - ToolmakerSteven log n
?真的吗?我不认为 del list[index]
的时间复杂度是 O(1)。 - user202729所以,您基本上想一次性删除多个元素?在这种情况下,要删除的下一个元素的位置将偏移由之前删除的元素数量确定。
我们的目标是删除所有预先计算出来的元音字母,它们的索引分别为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]
如果您想以任何顺序删除元素,那么这将变得更加复杂。在我看来,对to_delete
进行排序可能比弄清何时应该或不应该从index
中减去更容易。
我是Python的完全新手,目前我的编程水平可以说是相当粗糙和低劣的。但是我采用了一种方法,结合我在早期教程中学到的基本命令:
some_list = [1,2,3,4,5,6,7,8,10]
rem = [0,5,7]
for i in rem:
some_list[i] = '!' # mark for deletion
for i in range(0, some_list.count('!')):
some_list.remove('!') # remove
print some_list
很明显,由于必须选择一个“标记删除”字符,这有其局限性。
至于随着列表规模的增长,性能如何,我相信我的解决方案是次优的。然而,它很简单,我希望它能吸引其他初学者,并且在一些简单的情况下能够起作用,比如some_list
具有已知的格式,例如始终为数字...
这里有一种替代方法,不使用enumerate()创建元组(就像SilentGhost的原始回答中所示)。
我认为这种方法更易读。(也许如果我习惯使用enumerate()的话会感觉不同。)注意:我没有测试这两种方法的性能。
# 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 ]
注意:此处使用的是Python 2.7语法。对于Python 3,xrange
=> range
。
用法:
lst = [ 11*x for x in xrange(10) ]
somelist = delete_by_indices( lst, [0, 4, 5])
somelist:
[11, 22, 33, 66, 77, 88, 99]
--- 奖励 ---
从列表中删除多个值。也就是说,我们有要删除的值:
# 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 ]
使用方法:
somelist = delete__by_values( lst, [0, 44, 55] )
somelist:
[11, 22, 33, 66, 77, 88, 99]
这是与之前相同的答案,但这次我们提供了要删除的值[0, 44, 55]
。
[ value for (i, value) in enumerate(lst) if i not in set(indices) ]
。由于我还展示了如何按值删除,这也是一个更简单的情况,但可能会对其他人有所帮助,所以我会留下我的答案。 - ToolmakerSteveindices_as_set = set(indices)
,[ value for (i, value) in enumerate(lst) if i not in indices_as_set ]
,以加快速度。 - ToolmakerStevedelete__by_values()
中的双下划线有什么样式上的原因吗? - Tom一种使用列表索引值的替代列表推导方法:
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]
['b', 'c', 'e', 'f']