有没有一种简单的方法可以按值删除列表元素?

zjm*_*126 888 python list

a = [1, 2, 3, 4]
b = a.index(6)

del a[b]
print a
Run Code Online (Sandbox Code Playgroud)

以上显示以下错误:

Traceback (most recent call last):
  File "D:\zjm_code\a.py", line 6, in <module>
    b = a.index(6)
ValueError: list.index(x): x not in list
Run Code Online (Sandbox Code Playgroud)

所以我必须这样做:

a = [1, 2, 3, 4]

try:
    b = a.index(6)
    del a[b]
except:
    pass

print a
Run Code Online (Sandbox Code Playgroud)

但有没有更简单的方法来做到这一点?

Joh*_*rra 1485

要删除元素在列表中的第一个匹配项,只需使用list.remove:

>>> a = ['a', 'b', 'c', 'd']
>>> a.remove('b')
>>> print a
['a', 'c', 'd']
Run Code Online (Sandbox Code Playgroud)

请注意,它不会删除所有元素.使用列表理解.

>>> a = [10, 20, 30, 40, 20, 30, 40, 20, 70, 20]
>>> a = [x for x in a if x != 20]
>>> print a
[10, 30, 40, 30, 40, 70]
Run Code Online (Sandbox Code Playgroud)

  • 如果元素不在列表中,则失败.:) (137认同)
  • 为了澄清任何人的浏览,它会"失败",因为它会引发一个ValueError异常. (74认同)
  • @ibz list comprehension即使元素不在列表中也不会失败,是吗? (21认同)
  • 列表推导更改列表引用,因此如果某处有引用的副本,则不会执行删除操作. (9认同)

Dav*_*ebb 173

通常Python会抛出异常,如果你告诉它做一些它不能做的事情,那么你将不得不这样做:

if c in a:
    a.remove(c)
Run Code Online (Sandbox Code Playgroud)

要么:

try:
    a.remove(c)
except ValueError:
    pass
Run Code Online (Sandbox Code Playgroud)

只要它是您期望并正确处理的异常,异常并不一定是坏事.

  • 虽然在其他语言中也是如此,但在Python中,"要求宽恕比获得许可更容易".http://docs.python.org/2/glossary.html#term-eafp (76认同)
  • 预防胜于治疗.如果你可以先检查异常情况(例子a),你应该. (9认同)
  • @JFSebastian如果在线程之间共享一个列表而你没有应用关键部分那么你就会遇到更大的问题. (6认同)
  • @Gusdor:如果列表是在线程之间共享那么`a.remove(c)`可能会失败,尽管`if a in a check(`a`可以在`c in a` check之后在另一个线程中修改但是在`a.remove(c)`调用之前).`try/except`或lock可用于避免竞争条件. (5认同)
  • @Gusdor:究竟什么是更大的问题?Python 允许使用来自多个线程的列表,例如,CPython 在执行 `a.remove(c)` 时持有 GIL。请参阅[列出线程安全](http://stackoverflow.com/q/6319207/4279) (3认同)
  • @Gusdor,Pythonique习惯用法是在没有检查的情况下尝试并在发生异常时捕获异常.它效率更高(只有一次查找而不是两次),虽然有点丑陋 (2认同)
  • Python 的异常处理非常好,并且在未引发异常时比基于 if 的等效代码更快。但是,当引发异常时,速度会慢得多。如果引发异常的概率超过 5-10%,那么“三思而后行”策略可能会更快。 (2认同)

YOU*_*YOU 78

你可以做

a=[1,2,3,4]
if 6 in a:
    a.remove(6)
Run Code Online (Sandbox Code Playgroud)

但是上面需要在列表中搜索6次2次,所以尝试除了会更快

try:
    a.remove(6)
except:
    pass
Run Code Online (Sandbox Code Playgroud)


mat*_*urd 54

考虑:

a = [1,2,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)

要取出所有实例,可以在python中使用过滤器函数.例如,它看起来像:

a = list(filter(lambda x: x!= 2, a))
Run Code Online (Sandbox Code Playgroud)

所以,它会保留!= 2的所有元素.

要取出其中一个项目使用

a.remove(2)
Run Code Online (Sandbox Code Playgroud)

  • @OlafDietsche在Python 3.x中,它返回一个过滤器对象(在2.x中,它返回一个列表),所以我必须将"a"转换为列表,以便它具有任何功能. (7认同)

jfs*_*jfs 15

以下是如何在原地进行(没有列表理解):

def remove_all(seq, value):
    pos = 0
    for item in seq:
        if item != value:
           seq[pos] = item
           pos += 1
    del seq[pos:]
Run Code Online (Sandbox Code Playgroud)


gil*_*gil 12

如果你知道要删除什么值,这里有一个简单的方法(无论如何我都能想到这么简单):

a = [0, 1, 1, 0, 1, 2, 1, 3, 1, 4]
while a.count(1) > 0:
    a.remove(1)
Run Code Online (Sandbox Code Playgroud)

你会得到 [0, 0, 2, 3, 4]

  • 这是"O(n ^ 2)",其中理解是"O(n)". (12认同)
  • 为什么不使用`while in a::`作为循环结构? (4认同)

Gre*_*ade 11

另一种可能性是使用集合而不是列表,如果集合适用于您的应用程序.

IE如果您的数据没有订购,并且没有重复,那么

my_set=set([3,4,2])
my_set.discard(1)
Run Code Online (Sandbox Code Playgroud)

是没有错误的.

通常,列表只是实际无序的项目的便利容器.有些问题询问如何从列表中删除元素的所有出现.如果你不想在第一时间使用傻瓜,那么套装再次便利.

my_set.add(3)
Run Code Online (Sandbox Code Playgroud)

不会从上面更改my_set.


Fel*_*elk 10

如许多其他答案所述,list.remove()将起作用,但ValueError如果项目不在列表中,则抛出一个.使用python 3.4+,使用suppress contextmanager处理这个问题有一个有趣的方法:

from contextlib import suppress
with suppress(ValueError):
    a.remove('b')
Run Code Online (Sandbox Code Playgroud)


小智 8

通过使用list的remove方法,可以更轻松地在列表中查找值然后删除该索引(如果存在):

>>> a = [1, 2, 3, 4]
>>> try:
...   a.remove(6)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 3, 4]
>>> try:
...   a.remove(3)
... except ValueError:
...   pass
... 
>>> print a
[1, 2, 4]
Run Code Online (Sandbox Code Playgroud)

如果经常这样做,你可以将它包装在一个函数中:

def remove_if_exists(L, value):
  try:
    L.remove(value)
  except ValueError:
    pass
Run Code Online (Sandbox Code Playgroud)


Cha*_*ams 7

此示例很快,将从列表中删除值的所有实例:

a = [1,2,3,1,2,3,4]
while True:
    try:
        a.remove(3)
    except:
        break
print a
>>> [1, 2, 1, 2, 4]
Run Code Online (Sandbox Code Playgroud)

  • 如果你这样做,你应该只在`除了ValueError`之外``break`. (2认同)

小智 7

如果你的元素是不同的,那么一个简单的集合差异就可以了.

c = [1,2,3,4,'x',8,6,7,'x',9,'x']
z = list(set(c) - set(['x']))
print z
[1, 2, 3, 4, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)

  • 如果您的元素不同*并且您不关心订单*. (2认同)

And*_*bov 7

一行:

a.remove('b') if 'b' in a else None
Run Code Online (Sandbox Code Playgroud)

有时很有用。

更简单:

if 'b' in a: a.remove('b')
Run Code Online (Sandbox Code Playgroud)


Sup*_*ova 6

我们还可以使用.pop:

>>> lst = [23,34,54,45]
>>> remove_element = 23
>>> if remove_element in lst:
...     lst.pop(lst.index(remove_element))
... 
23
>>> lst
[34, 54, 45]
>>> 
Run Code Online (Sandbox Code Playgroud)


Ste*_*fan 5

这里的许多答案都涉及创建一个新列表。这涉及将旧列表中的所有数据复制到新列表(已删除的项目除外)。如果您的清单很大,您可能负担不起(或者您不应该愿意)。

在这些情况下,就地更改列表要快得多。如果您必须从列表中删除超过 1 个元素,这可能会很棘手。假设您循环列表并删除一个项目,然后列表发生变化,标准的 for 循环不会考虑到这一点。循环的结果可能不是你所期望的。

例子:

a = [0, 1, 2, 3, 4, 5]
for i in a:
    a.remove(i)  # Remove all items
print(a)

Out: [1, 3, 5]
Run Code Online (Sandbox Code Playgroud)

一个简单的解决方案是以相反的顺序循环遍历列表。在这种情况下你会得到:

a = [0, 1, 2, 3, 4, 5]
for i in reversed(a):
    a.remove(i)  # Remove all items
print(a)

Out: []
Run Code Online (Sandbox Code Playgroud)

然后,如果您只需要删除具有某些特定值的元素,您可以简单地将 an 放入if statement循环中,结果是:

a = [0, 1, 2, 3, 4, 5]
for i in reversed(a):
    if i == 2 or i == 3:  # Remove all items having value 2 or 3.
        a.remove(i)
print(a)

Out: [0, 1, 4, 5]
Run Code Online (Sandbox Code Playgroud)