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


1503

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

我找到了list.remove方法,但是说我要删除最后一个元素,该怎么做?似乎默认的remove搜索列表,但是我不希望执行任何搜索。


10
@smci:Python列表是基于数组的:要删除中间的一个项目,您必须向右移动所有项目以消除差距,这就是它O(n)及时运行的原因。deque()提供两端有效的操作,但在中间不提供O(1)插入/查找/删除。
jfs 2015年

@JFSebastian:cPython实现,是的,感谢您的指正。严格来说,语言规范未指定如何实现列表,替代实现可以选择使用链接列表。
smci 2015年

@smci:没有实际的Python实现会使用O(n)索引访问a[i](由于链接列表)。注意:基于数组的实现提供O(1)索引访问。
jfs

@JFSebastian:当然。我只是指出语言规范没有定义this,而是实现问题。(我很惊讶地发现事实并非如此。)
smci

@smci如果您的目标很广泛,那么我不确定如何优化任何东西。
尼克T

Answers:


1740

使用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]

是教程中的部分。


53
谢谢,pop和del有什么区别?
Joan Venge

37
del超载。例如,del a删除整个列表
Brian R. Bondy

34
另一个示例del a [2:4],删除元素2和3
Brian R. Bondy

307
pop()返回要删除的元素。删除只是删除。

13
我在那里看不到“链接列表”的证明。查看svn.python.org/projects/python/trunk/Objects/listobject.cPyList_GetItem()本质上如何返回((PyListObject *)op) -> ob_item[i];- i数组的第一个元素。
glglgl

648

您可能想要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']

105
不要忘记pop(-1)。是的,这是默认设置,但我更喜欢它,因此不必记住默认使用哪个最终流行音乐。
S.Lott

282
我不同意。如果您知道程序员的“ pop”的词源(就是删除并返回“堆栈”数据结构顶部的操作),那么pop()它本身就非常明显,同时由于冗余而pop(-1)可能会造成混乱。
coredumperror13年

a.pop(-1)删除最后一个?
zx1986

14
pop在大多数编程语言中,@ zx1986 a 通常会删除最后一项,就像在Python中一样。因此,无论您指定-1还是不指定什么都相同。
Pascal

30
顺便说一句,pop()返回它删除的任何元素。
鲍勃·斯坦

136

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

使用切片(这并不能代替从原始列表中删除项目):

(这也是使用Python列表时效率最低的方法,但是在使用不支持pop但却定义了a的用户定义对象时,这可能会很有用(但无效,我重申__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 )

这与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和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 None。同样,前两行正在加载全局值aindex


4
您的切片方法不会从列表中删除元素:而是会创建一个新的列表对象,其中包含除原始列表中的第i个条目之外的所有条目。原始列表保持不变。
Mark Dickinson 2014年

@MarkDickinson已对答案进行了编辑以使答案相同...请让我知道它现在看起来是否不错?
拉格夫房车

6
也许答案并不完全是关于主题的,但是如果您需要从不可变对象(例如元组)中省略一项,则索引方法很有用。在这种情况下,pop()和del()将不起作用。
Caleb 2014年

6
在整个文章中,@ rvraghav93在所有提出的方法中a = a[:index] + a[index+1 :],当涉及大量列表时,-trick是最省钱的。所有其他方法最终陷入僵局。因此,非常感谢
user3085931 2016年

3
确实,马克,你脾气暴躁。我喜欢这个答案,因为它确实是教学法。从这个答案以及所提供的反汇编详细信息以及对性能的影响中,我学到了很多。加上切片方法,是的,创建另一个对象,但是现在已指定它,有时这也是您所需要的。
Yohan Obadia

52

pop从列表中删除并保留项目也很有用。del实际在哪里丢弃物品。

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

>>> p = x.pop(1)
>>> p
    2

24

如果要删除列表中的特定位置元素,例如2th,3th和7th。你不能使用

del my_list[2]
del my_list[3]
del my_list[7]

由于删除第二个元素后,实际上删除的第三个元素是原始列表中的第四个元素。您可以过滤原始列表中的2th,3th和7th元素并获得一个新列表,如下所示:

new list = [j for i, j in enumerate(my_list) if i not in [2, 3, 7]]

19

这取决于您要做什么。

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



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]指向索引中的元素 xy-1。当我们将列表的该部分声明为空列表([])时,这些元素将被删除。


14

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

    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)

输出:acde


6
我喜欢这种解决方案,但是当然它假定您的列表没有重复项。
tommy.carstensen

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

3
这不是按索引删除,而是按匹配值删除。对于一些来这里的人来说,这可能是有价值的信息,但根本不会回答OP的问题。
安东,

8

如前所述,最佳实践是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
哪个版本的Python具有功能del()?对于该函数,您将列表作为该函数的第一个参数,然后提供索引,还是先提供索引,再提供列表?它返回不带项目的list参数,还是就地删除。我知道该del语句,但不知道具有相同名称的函数。
安通

8

听起来好像您不是在使用列表列表,所以我将简短说明。您要使用pop,因为它将删除元素而不是列表元素,因此应使用del。要调用python中的最后一个元素,它是“ -1”

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

1
pop()del都在提供的索引处删除元素,而与该元素本身是否为列表无关。a = [1, [2, 3], 4]; del a[1]; b = [1, [2, 3], 4]; b.pop(1); assert a == b
Anthon '18

8

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]

不起作用,答案是<map at 0x7f4d54109a58>。并且l是range(0,20)
Hitesh

7

使用“ del”功能:

del listName[-N]

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

del listName[-3:]

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

del listName[-8:]

2
del是一个声明。如果它是一个函数,那么您将不得不编写del(listame[-N])
Anthon '18

7

已经提到了如何从列表中删除单个元素以及不同方法具有哪些优点。但是请注意,删除多个元素可能会导致错误:

>>> 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]

4

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

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 '18年

3

您可以使用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]
>>> 

3

可以使用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]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.