如何按索引从列表中删除元素?
我找到了list.remove(),但这会缓慢地按值扫描列表中的项。
如何按索引从列表中删除元素?
我找到了list.remove(),但这会缓慢地按值扫描列表中的项。
当前回答
您可以只搜索要删除的项目。这真的很简单。例子:
letters = ["a", "b", "c", "d", "e"]
letters.remove(letters[1])
print(*letters) # Used with a * to make it unpack you don't have to (Python 3.x or newer)
输出:a c d e
其他回答
像其他提到的pop和del是删除给定索引项的有效方法。然而,仅仅为了完成(因为在Python中可以通过多种方式完成相同的任务):
使用切片(这不会从原始列表中就地删除项目):
(在使用Python列表时,这也是效率最低的方法,但在使用不支持pop但定义了__getitem__的用户定义对象时,这可能很有用(但我重申这不是有效的):
>>> a = [1, 2, 3, 4, 5, 6]
>>> index = 3 # Only positive index
>>> a = a[:index] + a[index+1 :]
# a is now [1, 2, 3, 5, 6]
注意:请注意,此方法不会像pop和del那样就地修改列表。它会创建两个列表副本(一个从开始到索引,但没有索引(a[:index]),一个在索引之后,直到最后一个元素(a[index+1:])),并通过添加这两个副本创建一个新的列表对象。然后将其重新分配给列表变量(a)。因此,旧列表对象被取消引用,因此被垃圾收集(前提是原始列表对象未被除a之外的任何变量引用)。
这使得该方法非常低效,并且还会产生不希望的副作用(特别是当其他变量指向未修改的原始列表对象时)。
感谢@MarkDickinson指出这一点。。。
堆栈溢出的答案解释了切片的概念。
还要注意,这只适用于正指数。
在与对象一起使用时,__getitem__方法必须已定义,更重要的是__add__方法必须定义为返回包含两个操作数中的项的对象。
本质上,这适用于类定义如下的任何对象:
class foo(object):
def __init__(self, items):
self.items = items
def __getitem__(self, index):
return foo(self.items[index])
def __add__(self, right):
return foo( self.items + right.items )
这适用于定义__getitem__和__add__方法的列表。
三种方式的效率比较:
假设以下是预定义的:
a = range(10)
index = 3
del object[index]方法:
迄今为止最有效的方法。它适用于定义__del__方法的所有对象。
拆卸如下:
代码:
def del_method():
global a
global index
del a[index]
拆卸:
10 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 DELETE_SUBSCR # This is the line that deletes the item
7 LOAD_CONST 0 (None)
10 RETURN_VALUE
None
pop方法:
它比del方法效率低,并且在需要获取已删除项时使用。
代码:
def pop_method():
global a
global index
a.pop(index)
拆卸:
17 0 LOAD_GLOBAL 0 (a)
3 LOAD_ATTR 1 (pop)
6 LOAD_GLOBAL 2 (index)
9 CALL_FUNCTION 1
12 POP_TOP
13 LOAD_CONST 0 (None)
16 RETURN_VALUE
切片和添加方法。
效率最低。
代码:
def slice_method():
global a
global index
a = a[:index] + a[index+1:]
拆卸:
24 0 LOAD_GLOBAL 0 (a)
3 LOAD_GLOBAL 1 (index)
6 SLICE+2
7 LOAD_GLOBAL 0 (a)
10 LOAD_GLOBAL 1 (index)
13 LOAD_CONST 1 (1)
16 BINARY_ADD
17 SLICE+1
18 BINARY_ADD
19 STORE_GLOBAL 0 (a)
22 LOAD_CONST 0 (None)
25 RETURN_VALUE
None
注意:在所有三个反汇编中,忽略最后两行,这两行基本上是返回None。前两行还加载全局值a和index。
可以使用del或pop,但我更喜欢del,因为您可以指定索引和切片,让用户对数据有更多的控制。
例如,从所示的列表开始,可以使用del作为切片删除其最后一个元素,然后可以使用pop从结果中删除最后一个。
>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]
如果要删除列表中特定位置的元素,如第2、第3和第7个元素,则不能使用
del my_list[2]
del my_list[3]
del my_list[7]
因为在删除第二个元素之后,您删除的第三个元素实际上是原始列表中的第四个元素。您可以过滤原始列表中的第2、第3和第7个元素,并获得一个新列表,如下所示:
new_list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]
这取决于你想做什么。
如果要返回删除的元素,请使用pop():
>>> l = [1, 2, 3, 4, 5]
>>> l.pop(2)
3
>>> l
[1, 2, 4, 5]
但是,如果您只想删除一个元素,请使用del:
>>> l = [1, 2, 3, 4, 5]
>>> del l[2]
>>> l
[1, 2, 4, 5]
此外,del允许您使用切片(例如del[2:])。
使用del语句:
del listName[-N]
例如,如果要删除最后3项,则代码应为:
del listName[-3:]
例如,如果要删除最后8项,则代码应为:
del listName[-8:]