【问题标题】:How to remove all the occurrences of a certain value in a Python list? [duplicate]如何删除 Python 列表中某个值的所有出现? [复制]
【发布时间】:2013-09-08 20:29:30
【问题描述】:

如何从下面的列表中删除两个出现的333

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]

我在 Python 2.7 命令行中输入了以下脚本

for num in a:
    if num == 333:
       a.remove(num)

但只删除了第一次出现的333

 >>> a
 [-1, 1, 66.25, 333, 1234.5]

如何删除所有出现的相同元素? 我希望能够指定我希望删除所有出现的元素并获得一个具有相同名称或其他名称的新列表

【问题讨论】:

  • 多次发布同一个问题并不会改变它仍然与已回答问题重复的事实。

标签: python list


【解决方案1】:

在这里使用列表推导:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> [item for item in a if item != 333]
[-1, 1, 66.25, 1234.5]

您的方法无效,因为you're modifying a list while iterating over it

for num in a[:]:  #iterate over a shallow copy
    if num == 333:
       a.remove(num)

要获取唯一项目的列表,请使用集合:

>>> seen = set()
>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> [item for item in a if item not in seen and not seen.add(item)]
[-1, 1, 66.25, 333, 1234.5]

如果顺序无关紧要:

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> list(set(a))
[66.25, 1, 333, -1, 1234.5]

【讨论】:

  • 那是线性时间和线性空间。考虑 while 333 in a: a.remove(333) 的二次时间且没有额外空间
  • @inspectorG4dget for _ in range(a.count(333)): a.remove(333) 效率稍高。
  • @Bakuriu:你是对的。你的是 2x 线性的,我的建议是二次的!
  • @Varuna 这里已经解释过了:loop forgets to remove some items
  • @Varuna 它返回一个新列表,如果要修改相同的列表,请使用低效的list.remove 方法。要修改对象 a 就地使用: a[:] = [item for item in a if item != 333] ,这也会创建一个新列表,但 a 的 id() 不会改变。
【解决方案2】:

由于您询问如何删除元素,我将重新分配列表作为切片。

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> a[:] = [item for item in a if item != 333]

这将在内存中创建一个新列表,通常这是可以接受的,但如果您想避免这种情况而不调用 remove,这将多次检查相同的项目。

>>> a = [-1, 1, 66.25, 333, 333, 1234.5]
>>> for i in range(len(a) - 1, -1, -1):  # iterate over reversed indices's
>>>     if a[i] == 333:
>>>         del a[i]

这样做的好处是它首先删除最后的项目(这在 CPython 中更快)。

请注意,在 Python 中从列表的开头-中间删除项目并不是最理想的。无论您使用哪种方法(del list[index]list.remove),如果列表很大并且必须删除许多项目,这意味着 Python 需要大量调整列表的大小,在这种情况下,我建议使用 list-comprehension制作一个新列表。

【讨论】:

  • 只是好奇,但有必要在第二行的a 之后添加[:] 吗?当我测试它时,删除 [:] 并没有什么不同......
  • @Lucas - 是的,它有所不同,因为问题要求从列表中删除,删除 [:] 将分配一个新变量,而不是就地修改列表,这很重要如果列表在其他地方被引用,则不同。
【解决方案3】:

我想你在这里想要的是这样的

a = [-1, 1, 66.25, 333, 333, 1234.5]
a = [el for el, count in collections.Counter(a).items() if count == 1]

这将从任何值的列表中删除元素,前提是它们多次出现。

【讨论】:

  • 这实际上回答了这个问题。其他答案只删除了333的出现,不是通用的解决方案。
  • 我认为这不是 OP 想要的;我认为他只是用尴尬的标题措辞。
  • 可以看到问题的最后一行:How to remove all the occurrences of the same element?
  • 但是 OP 在他们的代码中明确使用了:if num == 333。我会使用来自 itertools 的 set 或 uniqueverseen 配方,而不是 collections.Counter,因为这样也会保留订单。
  • 标题准确地表达了我要问的问题,在这种情况下,列表中有两次出现相同的元素 333。我使用 333 只是为了测试我的方法是否有效。在docs.python.org/2/tutorial/datastructures.html 的描述中,它说 list.remove(x) 删除了第一次遇到的元素。我认为通过使用 remove() 删除了一个元素,并且在 for 循环的下一次迭代中下一次出现相同的元素元素将被遇到并将被删除
【解决方案4】:

在以下代码中,从 [5,3,4,7,8,4] 列表中删除了 4 个数字

>>> def pp(x):
...     if x==4:
...             return False
...     else:
...             return True
... 
>>> filter(pp, [5,3,4,7,8,4])

输出

[5, 3, 7, 8]

【讨论】:

  • filter(lambda x: x != 4, [5,3,4,7,8,4])
猜你喜欢
  • 1970-01-01
  • 2010-11-12
  • 1970-01-01
  • 1970-01-01
  • 2011-01-31
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多