如何按索引从列表中删除元素

How to remove an element from a list by index

提问人:Joan Venge 提问时间:3/10/2009 最后编辑:Mateen UlhaqJoan Venge 更新时间:8/31/2022 访问量:3973473

问:

如何按索引从列表中删除元素?

我发现,但这会按值缓慢地扫描列表中的项目。list.remove()

Python 列表 索引

评论

18赞 jfs 9/8/2015
@smci:Python 列表是基于数组的:要删除中间的项目,您必须移动右侧的所有项目以消除间隙,这就是它在时间操作中的原因。 在两端提供高效的操作,但不提供中间的 O(1) 插入/查找/删除。O(n)deque()
2赞 smci 9/9/2015
@J.F.Sebastian:cPython实现,是的,谢谢你纠正我。严格来说,语言规范没有指定如何实现列表,替代实现可以选择使用链表。
0赞 jfs 2/23/2016
@smci:没有实际的 Python 实现会使用索引访问(由于链接列表)。注意:基于数组的实现提供索引访问。O(n)a[i]O(1)
3赞 smci 2/27/2016
@J.F.Sebastian:当然。我只是指出语言规范没有定义这一点,这是一个实现问题。(我很惊讶地发现它没有。
2赞 smci 8/21/2017
@NickT:我只是提醒大家,由于没有在语言规范中定义,所以要区分何时是实现定义的。正是这种假设在 2.x 中引起了哈希不稳定(平台之间)的重大悲痛。显然,大多数 Python 列表的理性实现永远不会选择链接列表,因为我们希望基本操作是 O(1)。就这样。

答:

923赞 Jarret Hardie 3/10/2009 #1

您可能想要:pop

a = ['a', 'b', 'c', 'd']
a.pop(1)

# now a is ['a', 'c', 'd']

默认情况下,不带任何参数会删除最后一项:pop

a = ['a', 'b', 'c', 'd']
a.pop()

# now a is ['a', 'b', 'c']

评论

72赞 Bob Stein 1/30/2016
顺便说一句,返回它删除的任何元素。pop()
0赞 Davis Herring 10/1/2017
@S.Lott:它默认使用结尾,因为它是 O(1);一开始是 O(n)。
3赞 Seb 12/5/2020
这个答案是不正确的。 返回从数组中删除的值,而不是没有要删除的值的数组,如代码注释中所示。我相信它没有回答最初的问题,因为它没有被问到如何从数组中提取值,而是将其删除。pop()
2赞 b4ux1t3 3/2/2021
@Seb,您是对的,因为它返回了您删除的值,但问题中没有要求说必须重新生成或返回列表。由于更改了列表,因此它完全满足了问题提出的要求,尽管返回值是多余的。我什至认为 pop 比公认的答案更正确,因为与 相比,pop 是一个与正在运行的程序的内存管理密切相关的关键字,而 是 Python 中列表对象的一个特性。popdellist.pop
0赞 Charlie Parker 9/17/2021
总之,我是否使用或修改和删除该元素而没有奇怪的错误?delpop
2508赞 unbeknown 3/10/2009 #2

使用并指定要删除的元素的索引:del

>>> a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> del a[-1]
>>> a
[0, 1, 2, 3, 4, 5, 6, 7, 8]

还支持切片:

>>> del a[2:4]
>>> a
[0, 1, 4, 5, 6, 7, 8, 9]

这是教程中的部分。

评论

74赞 Joan Venge 3/10/2009
谢谢,pop 和 del 有什么区别?
47赞 Brian R. Bondy 3/10/2009
del 已过载。例如,del a 删除整个列表
42赞 Brian R. Bondy 3/10/2009
另一个例子 del a[2:4],删除了元素 2 和 3
357赞 3/10/2009
pop() 返回要删除的元素。del 只是删除了 is。
15赞 glglgl 9/9/2013
我在那里看不到“链表”的证明。看看 svn.python.org/projects/python/trunk/Objects/listobject.c 本质上是如何返回的 - 数组的第 th 个元素。PyList_GetItem()((PyListObject *)op) -> ob_item[i];i
63赞 boatcoder 10/19/2013 #3

POP 还可用于从列表中删除和保留项目。实际上在哪里丢弃了该项目。del

>>> x = [1, 2, 3, 4]

>>> p = x.pop(1)
>>> p
    2
189赞 Raghav RV 6/22/2014 #4

像提到的其他人一样pop 和 del 是删除给定索引项的有效方法。然而,只是为了完成(因为在 Python 中可以通过多种方式完成同样的事情):

使用切片(这不会从原始列表中就地删除项目):

(此外,在使用 Python 列表时,这将是效率最低的方法,但在处理不支持 pop 但确实定义了 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]

注意:请注意,此方法不会像 和 那样修改列表。相反,它会创建列表的两个副本(一个从开始到索引,但没有它 (),另一个在索引之后直到最后一个元素 ()),并通过添加两者来创建一个新的列表对象。然后将其重新分配给列表变量 ()。因此,旧的列表对象被取消引用,因此被垃圾回收(前提是原始列表对象没有被除 a 以外的任何变量引用)。popdela[:index]a[index+1:]a

这使得这种方法效率非常低下,并且还可能产生不良的副作用(尤其是当其他变量指向未修改的原始列表对象时)。

感谢@MarkDickinson指出这一点......

Stack Overflow 答案解释了切片的概念。

另请注意,这仅适用于正指数。

与对象一起使用时,必须已定义方法,更重要的是,必须已定义 __add__ 方法以返回包含来自两个操作数的项的对象。__getitem__

从本质上讲,这适用于类定义如下的任何对象:

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 )

这适用于哪些定义和方法。list__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

slice and add 方法。

效率最低。

法典:

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

注意:在所有三个反汇编中,忽略最后两行,基本上是 .此外,前两行正在加载全局值和 。return Noneaindex

评论

6赞 Mark Dickinson 6/22/2014
切片方法不会从列表中删除元素:而是创建一个新的列表对象,其中包含原始列表中除第 i 个条目之外的所有条目。原始列表保持不变。
0赞 Raghav RV 6/23/2014
@MarkDickinson 已经编辑了答案以澄清相同的内容......请让我知道它现在看起来不错吗?
8赞 Caleb 12/19/2014
也许答案并不完全在主题上,但如果您需要从不可变对象(例如元组)中省略某个项,则索引方法很有用。pop() 和 del() 在这种情况下将不起作用。
7赞 user3085931 3/5/2016
@rvraghav93在整个帖子中提出的所有方法中,当涉及到巨大的列表时,-trick 是 savest。所有其他方法都陷入了僵局。所以非常感谢你a = a[:index] + a[index+1 :]
4赞 Yohan Obadia 5/8/2017
马克,你确实脾气暴躁。这个答案是我更喜欢的,因为它确实具有教育意义。我从这个答案和提供的反汇编细节以及对性能的影响中学到了很多东西。加上切片方法,是的,创建另一个对象,但现在它被指定了,有时这也是你需要的。
21赞 Mayur Koshti 10/5/2015 #5

通常,我使用以下方法:

>>> myList = [10,20,30,40,50]
>>> rmovIndxNo = 3
>>> del myList[rmovIndxNo]
>>> myList
[10, 20, 30, 50]
4赞 pyman 2/1/2016 #6

可以使用 del 或 pop,但我更喜欢 del,因为您可以指定索引和切片,让用户对数据有更多的控制权。

例如,从显示的列表开始,可以删除其最后一个元素作为切片,然后可以使用 从结果中删除最后一个元素。delpop

>>> l = [1,2,3,4,5]
>>> del l[-1:]
>>> l
[1, 2, 3, 4]
>>> l.pop(-1)
4
>>> l
[1, 2, 3]
11赞 litepresence 6/28/2016 #7

如前所述,最佳实践是 del();或者 pop() 如果你需要知道这个值。

另一种解决方案是仅重新堆叠所需的元素:

    a = ['a', 'b', 'c', 'd'] 

    def remove_element(list_,index_):
        clipboard = []
        for i in range(len(list_)):
            if i is not index_:
                clipboard.append(list_[i])
        return clipboard

    print(remove_element(a,2))

    >> ['a', 'b', 'd']

ETA: 嗯...不会对负指数值起作用,会思考和更新

我想

if index_<0:index_=len(list_)+index_

会修补它......但突然之间,这个想法似乎很脆弱。不过,这是一个有趣的思想实验。似乎应该有一种“适当”的方法来使用 append() / 列表推导来做到这一点。

思考

评论

1赞 Anthon 12/2/2018
哪个版本的 Python 有函数?对于该函数,您提供列表作为该函数的第一个参数,然后是索引,还是先提供索引,然后再提供列表?它是否返回不带项的列表参数,或者是否就地删除。我知道这个语句,但不知道同名的函数。del()del
5赞 Aashutosh jha 12/13/2016 #8

您可以使用 del 或 pop 根据索引从列表中删除元素。Pop 将打印它正在从列表中删除的成员,而列表删除该成员而不打印它。

>>> a=[1,2,3,4,5]
>>> del a[1]
>>> a
[1, 3, 4, 5]
>>> a.pop(1)
 3
>>> a
[1, 4, 5]
>>> 
9赞 Mo Ali 12/27/2016 #9

这听起来不像是你在处理列表列表,所以我会保持简短。你想使用 pop,因为它会删除元素而不是列表元素,你应该使用 del。要调用 python 中的最后一个元素,它是“-1”

>>> test = ['item1', 'item2']
>>> test.pop(-1)
'item2'
>>> test
['item1']

评论

2赞 Anthon 12/2/2018
pop()并且两者都删除了提供的索引处的元素,而与该元素本身是否为列表无关。dela = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b
18赞 SollyBunny 2/15/2017 #10

您可以只搜索要删除的项目。这真的很简单。 例:

    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

评论

7赞 tommy.carstensen 8/25/2018
我喜欢这个解决方案,但当然它假设您的列表没有重复项。
12赞 Jitesh Mohite 5/14/2017 #11

使用以下代码从列表中删除元素:

list = [1, 2, 3, 4]
list.remove(1)
print(list)

output = [2, 3, 4]

如果要从列表中删除索引元素数据,请使用:

list = [1, 2, 3, 4]
list.remove(list[2])
print(list)
output : [1, 2, 4]

评论

2赞 tommy.carstensen 8/25/2018
附带警告,您的列表不能包含重复项。
4赞 Anthon 12/2/2018
这不是按索引删除,而是按匹配值删除。对于访问这里的一些人来说,这可能是有价值的信息,但根本没有试图回答 OP 的问题。
29赞 lloydyu24 6/4/2017 #12

使用 del 语句:

del listName[-N]

例如,如果要删除最后 3 项,则代码应为:

del listName[-3:]

例如,如果要删除最后 8 个项目,则代码应为:

del listName[-8:]
24赞 Neil 8/11/2017 #13

这取决于你想做什么。

如果要返回已删除的元素,请使用: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]

此外,还允许您使用切片(例如 )。deldel[2:]

11赞 Jo Ja 9/26/2017 #14

l - 值列表;我们必须从 inds2rem 列表中删除索引。

l = range(20)
inds2rem = [2,5,1,7]
map(lambda x: l.pop(x), sorted(inds2rem, key = lambda x:-x))

>>> l
[0, 3, 4, 6, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

评论

0赞 Hitesh 5/30/2018
不工作,答案是.l 是范围 (0,20)<map at 0x7f4d54109a58>
22赞 Andreas Chatzivasileiadis 10/30/2017 #15

另一种按索引从列表中删除元素的方法。

a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

# remove the element at index 3
a[3:4] = []
# a is now [0, 1, 2, 4, 5, 6, 7, 8, 9]

# remove the elements from index 3 to index 6
a[3:7] = []
# a is now [0, 1, 2, 7, 8, 9]

a[x:y] 指向从 index 到 的元素。当我们将列表的该部分声明为空列表 () 时,这些元素将被删除。xy-1[]

67赞 xiaojia zhang 7/24/2018 #16

如果要删除列表中特定位置的元素,例如第 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]]

评论

1赞 Magnus 7/23/2020
符合我的需要。我需要浏览一个列表并删除其中的一些。因此,使用此方法,我将只将要删除的元素的索引保存在另一个列表中,然后在最后我将使用您提供的方法一次删除它们。
4赞 joanis 10/4/2021
你仍然可以重复调用,只要你先从最大的索引开始,就像在 nspo 的回答中一样。del
7赞 U13-Forward 9/23/2018 #17

或者,如果应删除多个索引:

print([v for i,v in enumerate(your_list) if i not in list_of_unwanted_indexes])

当然,也可以做:

print([v for i,v in enumerate(your_list) if i != unwanted_index])

评论

1赞 Anthon 12/2/2018
为什么不按相反的顺序对索引列表进行排序,然后逐个删除它们呢?这样你就不必制作一个新列表。
43赞 nspo 8/20/2019 #18

已经提到了如何从列表中删除单个元素以及不同方法的优点。但请注意,删除多个元素可能会出现一些错误:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in indices:
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 7, 9]

原始列表的要素 3 和 8(不是 3 和 7)已被删除(因为列表在循环过程中被缩短了),这可能不是本意。如果要安全地删除多个索引,则应首先删除索引最高的元素,例如:

>>> l = [0,1,2,3,4,5,6,7,8,9]
>>> indices=[3,7]
>>> for i in sorted(indices, reverse=True):
...     del l[i]
... 
>>> l
[0, 1, 2, 4, 5, 6, 8, 9]