从列表中删除所有出现的值?

riz*_*iza 341 python list

在Python remove()中将删除列表中第一次出现的值.

如何从列表中删除所有出现的值,而不对列表进行排序?

这就是我的想法.

>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]
Run Code Online (Sandbox Code Playgroud)

Mar*_*off 461

功能方法:

2.X

>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]
Run Code Online (Sandbox Code Playgroud)

3.X

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]
Run Code Online (Sandbox Code Playgroud)

要么

>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]
Run Code Online (Sandbox Code Playgroud)

  • 使用list comprehension over filter + lambda; 前者除了通常更有效之外更具可读性. (114认同)
  • habnabit建议的代码如下所示:`[y y in x in y!= 2]` (84认同)
  • s /一般/一般是/ (16认同)
  • 我不会称这种解决方案为最佳.在浏览代码时,列表推导更快更容易理解.这更像是一种比Python更为Perl的方式. (8认同)
  • -1 用于直接调用 `__ne__`。比较两个值是一个比仅在其中一个值上调用 `__eq__` 或 `__ne__` 复杂得多的过程。它可能在这里正常工作,因为您只是在比较数字,但在一般情况下这是不正确的并且是一个错误。 (7认同)
  • @habnabit 这可能会被 python 工作人员否决,但是列表理解更具可读性的说法在一般情况下可能是错误的。过滤器高阶函数概念存在于比列表推导式概念更多的编程语言中(更不用说 Python 中存在的特定列表推导式语法了)。尽管我同意列表理解是在 Python 中完成此任务的“正确”方法,但如果有人感到困惑为什么这个答案的赞成票数是“正确”答案的两倍,那就是原因。 (3认同)
  • **不要**像这样直接使用 dunder 方法。一个简单的例子: `(2).__ne__(2.)` 返回 `NotImplemented`,这是 *truthy* (2认同)

mha*_*wke 194

您可以使用列表理解:

def remove_values_from_list(the_list, val):
   return [value for value in the_list if value != val]

x = [1, 2, 3, 4, 2, 2, 3]
x = remove_values_from_list(x, 2)
print x
# [1, 3, 4, 3]
Run Code Online (Sandbox Code Playgroud)

  • 这不会修改原始列表但会返回新列表. (11认同)
  • 我投了这票,因为经过6年的Python我仍然不理解Lambdas :) (8认同)
  • 如何在不检查项目的情况下删除项目? (7认同)
  • @Selinap:不,这是最佳的,因为它只扫描列表一次.在原始代码中,`in`操作符和`remove`方法都会扫描整个列表(直到找到匹配项为止),因此您最终会以这种方式多次扫描列表. (6认同)
  • @mhawke,@ John Y:只使用x [:] = ...而不是x =并且它将是"就地"而不是重新绑定名称'x'(速度基本相同,比x快很多) .remove可以!!!). (4认同)
  • @Benjamin Lambdas也被称为"匿名函数".基本上,它们是您即时创建的功能,通常用于特定目的,并且只是注入代码中的某个位置.作为旁注,我不完全确定Python,但在其他语言(如`Scheme`)中,您编写的每个函数实际上都是内部转换并存储为Lambda表达式.给它一些名称来引用它,并通过该名称引用它,是基础Lambda表达式的语法糖. (2认同)

A. *_*ady 102

如果必须修改原始列表,则仍可以使用切片分配,同时仍使用有效的列表推导(或生成器表达式).

>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]
Run Code Online (Sandbox Code Playgroud)

  • 我喜欢这个,因为它修改了x引用的列表.如果对该列表有任何其他引用,它们也会受到影响.这与`x = [v for x in x!x!= 2]`提案相反,它创建一个新列表并更改x以引用它,保持原始列表不变. (7认同)

fun*_*unk 39

以更抽象的方式重复第一篇文章的解决方案:

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

  • 不过,这是O(n*n). (15认同)
  • 绝对是最易读的解决方案. (5认同)
  • 考虑`x = [1] * 10000 + [2] * 1000`。循环体执行 1000 次,每次调用 .remove() 都必须跳过 10000 个元素。对我来说这闻起来像 O(n*n) 但不是证据。我认为证据是假设列表中 2 的数量与其长度成正比。然后,该比例因子在大 O 符号中消失了。然而,最好的情况是,列表中只有恒定数量的 2,不是 O(n^2),而是 O(2n),也就是 O(n)。 (3认同)

Sha*_*eem 16

查看简单解决

方案解决方案1:

>>> [i for i in x if i != 2]
Run Code Online (Sandbox Code Playgroud)

这将返回一个列表,其中包含x没有2

解决方案2的所有元素:

>>> while 2 in x : x.remove(2)
Run Code Online (Sandbox Code Playgroud)

  • 这些解决方案都已经发布。几年前。 (5认同)

Pau*_*l S 10

上面的所有答案(除了Martin Andersson)都会创建一个没有所需项目的新列表,而不是从原始列表中删除项目.

>>> import random, timeit
>>> a = list(range(5)) * 1000
>>> random.shuffle(a)

>>> b = a
>>> print(b is a)
True

>>> b = [x for x in b if x != 0]
>>> print(b is a)
False
>>> b.count(0)
0
>>> a.count(0)
1000

>>> b = a
>>> b = filter(lambda a: a != 2, x)
>>> print(b is a)
False
Run Code Online (Sandbox Code Playgroud)

如果您对列表有其他引用,这可能很重要.

要修改列表,请使用这样的方法

>>> def removeall_inplace(x, l):
...     for _ in xrange(l.count(x)):
...         l.remove(x)
...
>>> removeall_inplace(0, b)
>>> b is a
True
>>> a.count(0)
0
Run Code Online (Sandbox Code Playgroud)

就速度而言,我的笔记本电脑上的结果是(所有5000个条目列表中删除了1000个条目)

  • 列表理解 - 约400us
  • 过滤器 - 约900us
  • .remove()循环 - 50ms

所以.remove循环慢了大约100倍........嗯,也许需要一种不同的方法.我发现最快的是使用列表推导,但随后替换原始列表的内容.

>>> def removeall_replace(x, l):
....    t = [y for y in l if y != x]
....    del l[:]
....    l.extend(t)
Run Code Online (Sandbox Code Playgroud)
  • removeall_replace() - 450us


Mar*_*son 6

以可读性为代价,我认为这个版本稍微快一些,因为它不会强制重新检查列表,因此无论如何都要执行完全相同的工作删除:

x = [1, 2, 3, 4, 2, 2, 3]
def remove_values_from_list(the_list, val):
    for i in range(the_list.count(val)):
        the_list.remove(val)

remove_values_from_list(x, 2)

print(x)
Run Code Online (Sandbox Code Playgroud)


Amr*_*Amr 6

你可以这样做

while 2 in x:   
    x.remove(2)
Run Code Online (Sandbox Code Playgroud)

  • 这是一个糟糕的解决方案,因为对于n次出现2,列表必须遍历2*n次. (3认同)

Jar*_*ows 5

要删除所有重复的事件并在列表中留下一个:

test = [1, 1, 2, 3]

newlist = list(set(test))

print newlist

[1, 2, 3]
Run Code Online (Sandbox Code Playgroud)

这是我用于 Project Euler 的函数:

def removeOccurrences(e):
  return list(set(e))
Run Code Online (Sandbox Code Playgroud)

  • -1,这不是 OP 问题的答案。它是一种去除重复项的解决方案,这是完全不同的事情。 (7认同)
  • 这将从列表中删除任何排序。 (6认同)
  • @JaredBurrows 可能是因为它没有回答目前的问题,而是一个完全不同的问题。 (4认同)
  • 我需要在具有 250k 值的向量上执行此操作,它的工作原理非常棒。 (2认同)

Max*_*axU 5

针对具有 1.000.000 个元素的列表/数组的 Numpy 方法和计时:

时间:

In [10]: a.shape
Out[10]: (1000000,)

In [13]: len(lst)
Out[13]: 1000000

In [18]: %timeit a[a != 2]
100 loops, best of 3: 2.94 ms per loop

In [19]: %timeit [x for x in lst if x != 2]
10 loops, best of 3: 79.7 ms per loop
Run Code Online (Sandbox Code Playgroud)

结论:与列表理解方法相比,numpy 快 27 倍(在我的笔记本上)

PS,如果您想将常规 Python 列表转换lst为 numpy 数组:

arr = np.array(lst)
Run Code Online (Sandbox Code Playgroud)

设置:

import numpy as np
a = np.random.randint(0, 1000, 10**6)

In [10]: a.shape
Out[10]: (1000000,)

In [12]: lst = a.tolist()

In [13]: len(lst)
Out[13]: 1000000
Run Code Online (Sandbox Code Playgroud)

查看:

In [14]: a[a != 2].shape
Out[14]: (998949,)

In [15]: len([x for x in lst if x != 2])
Out[15]: 998949
Run Code Online (Sandbox Code Playgroud)


Ank*_*rma 5

a = [1, 2, 2, 3, 1]
to_remove = 1
a = [i for i in a if i != to_remove]
print(a)
Run Code Online (Sandbox Code Playgroud)

也许不是最pythonic但对我来说仍然是最简单的哈哈