假设我有这个列表:
list = [a, b, c, d, e, f, g]
如何同时删除索引为2, 3, 4
和5
的元素?
pop()
方法不支持同时删除多个值,我该如何实现?
del my_list[2:6]
这将删除从2开始并在6之前结束的切片。
从您的问题中无法确定您是否需要删除任意集合的索引,还是它将始终是一系列连续的索引。
如果您有任意集合的索引,则:
indexes = [2, 3, 5]
for index in sorted(indexes, reverse=True):
del my_list[index]
请注意,您需要以相反的顺序删除它们,这样就不会影响后续的索引。
remove_indices = [1,2,3]
somelist = [i for j, i in enumerate(somelist) if j not in remove_indices]
示例:
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]
remove_indices
转换为一个set
! - c z针对不同方法的性能没有太多提示,因此我在所有三种一般不同的方法中测试了从50000个项目中删除5000个项目的测试,对于我来说numpy是赢家(如果你的元素适合numpy):
这是我计时的代码(在第三个函数中,如果直接在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
# ...
id_to_del
转换为一个集合,那么del_list_indexes
的速度应该会更快。 - C. Yduqoliset
进行enumerate
,我得到的时间是:enumerate
=0.0041,del
=0.035,numpy
=0.0079。正如预期的那样,enumerate
是最快的。 - c z如果您可以使用numpy,那么您可以删除多个索引:
>>> import numpy as np
>>> a = np.arange(10)
>>> np.delete(a,(1,3,5))
array([0, 2, 4, 6, 7, 8, 9])
如果您使用 np.r_
,您可以将切片与单独的索引组合:
>>> np.delete(a,(np.r_[0:5,7,9]))
array([5, 6, 8])
然而,删除不是在原地进行的,所以您必须对其进行分配。
如果它们是连续的,你只需要这样做
x[2:6] = []
如果你想要移除非连续的索引,那就需要有点技巧了。
x = [v for i,v in enumerate(x) if i not in frozenset((2,3,4,5))]
lst = ['a', 'b', 'c', 'd', 'e', 'f', 'g'];
lst = lst[0:2] + lst[6:]
这是一个单步操作。它不使用循环,因此执行速度快。它使用列表切片。
lst
,因为list
是Python数据类型。之所以没有人建议这个作为解决方案,是因为这会创建一个新的列表对象(基于原始内容),而不是实际修改原始列表对象。由于最终结果相似,我会点赞你的答案。欢迎来到[se]。 - Anthony Geoghegan另一种选项(在原处,任意组合的索引):
_marker = object()
for i in indices:
my_list[i] = _marker # marked for deletion
obj[:] = [v for v in my_list if v is not _marker]
虽然这是一个老问题,但我有一个答案。
首先,像这样浏览列表的元素:
for x in range(len(yourlist)):
print '%s: %s' % (x, yourlist[x])
def multipop(yourlist, itemstopop):
result = []
itemstopop.sort()
itemstopop = itemstopop[::-1]
for x in itemstopop:
result.append(yourlist.pop(x))
return result
In [73]: mylist = ['a','b','c','d','charles']
In [76]: for x in range(len(mylist)):
mylist[x])
....:
0: a
1: b
2: c
3: d
4: charles
...
In [77]: multipop(mylist, [0, 2, 4])
Out[77]: ['charles', 'c', 'a']
...
In [78]: mylist
Out[78]: ['b', 'd']
my_list.pop(index)
代替del my_list[index]
,会有什么不同?这对效率或语义有影响吗? - Levondel
,虽然两种方法都可以。 - Pro Q