【发布时间】:2010-11-12 12:40:48
【问题描述】:
在 Python 中,remove() 将删除列表中第一次出现的值。
如何从列表中删除所有个值?
这就是我的想法:
>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]
【问题讨论】:
在 Python 中,remove() 将删除列表中第一次出现的值。
如何从列表中删除所有个值?
这就是我的想法:
>>> remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
[1, 3, 4, 3]
【问题讨论】:
功能方法:
Python 3.x
>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter((2).__ne__, x))
[1, 3, 3, 4]
或
>>> x = [1,2,3,2,2,2,3,4]
>>> list(filter(lambda a: a != 2, x))
[1, 3, 3, 4]
Python 2.x
>>> x = [1,2,3,2,2,2,3,4]
>>> filter(lambda a: a != 2, x)
[1, 3, 3, 4]
【讨论】:
[y for y in x if y != 2]
__ne__。比较两个值是一个比仅在其中一个上调用__eq__ 或__ne__ 复杂得多的过程。它可能在这里正常工作,因为您只是在比较数字,但在一般情况下这是不正确的并且是一个错误。
您可以使用列表推导:
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]
【讨论】:
in 运算符和 remove 方法都会扫描整个列表(直到找到匹配项),因此您最终会以这种方式多次扫描列表。
如果必须修改原始列表,您可以使用切片分配,同时仍然使用有效的列表推导(或生成器表达式)。
>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> x[:] = (value for value in x if value != 2)
>>> x
[1, 3, 4, 3]
【讨论】:
x = [ v for v in x if x != 2 ] 提案形成对比,后者创建一个新列表并更改 x 以引用它,而原始列表保持不变。
以更抽象的方式重复第一篇文章的解决方案:
>>> x = [1, 2, 3, 4, 2, 2, 3]
>>> while 2 in x: x.remove(2)
>>> x
[1, 3, 4, 3]
【讨论】:
x = [1] * 10000 + [2] * 1000。循环体执行 1000 次,并且 .remove() 每次调用时都必须跳过 10000 个元素。对我来说,这闻起来像 O(n*n),但没有证据。我认为证明是假设列表中 2 的数量与其长度成正比。然后,该比例因子在大 O 表示法中消失了。不过,最好的情况是,列表中只有恒定数量的 2,不是 O(n^2),而是 O(2n),即 O(n)。
查看简单的解决方案
>>> [i for i in x if i != 2]
这将返回一个列表,其中包含 x 的所有元素,但不包含 2
【讨论】:
列表理解的更好解决方案
x = [ i for i in x if i!=2 ]
【讨论】:
上述所有答案(除了 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
如果您有其他对列表的引用,这可能很重要。
要就地修改列表,请使用类似这样的方法
>>> 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
就速度而言,我笔记本电脑上的结果是(全部在 5000 个条目列表中,删除了 1000 个条目)
所以 .remove 循环大约慢了 100 倍......嗯,也许需要一种不同的方法。我发现最快的是使用列表推导,然后替换原始列表的内容。
>>> def removeall_replace(x, l):
.... t = [y for y in l if y != x]
.... del l[:]
.... l.extend(t)
【讨论】:
def remove_all(x, l): return [y for y in l if y != x] 然后l = remove_all(3,l)
针对具有 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
结论: numpy 比列表理解方法快 27 倍(在我的笔记本上)
PS 如果你想将你的常规 Python 列表 lst 转换为 numpy 数组:
arr = np.array(lst)
设置:
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
检查:
In [14]: a[a != 2].shape
Out[14]: (998949,)
In [15]: len([x for x in lst if x != 2])
Out[15]: 998949
【讨论】:
以可读性为代价,我认为这个版本会稍微快一些,因为它不会强制 while 重新检查列表,因此无论如何都要做与 remove 完全相同的工作:
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)
【讨论】:
要删除所有重复的匹配项并在列表中保留一个:
test = [1, 1, 2, 3]
newlist = list(set(test))
print newlist
[1, 2, 3]
这是我用于 Project Euler 的函数:
def removeOccurrences(e):
return list(set(e))
【讨论】:
a = [1, 2, 2, 3, 1]
to_remove = 1
a = [i for i in a if i != to_remove]
print(a)
也许不是最pythonic,但对我来说仍然是最简单的哈哈
【讨论】:
如果您不关心列表顺序,如果您确实关心最终顺序,我相信这可能比任何其他方式都快,存储原始索引并以此为依据。
category_ids.sort()
ones_last_index = category_ids.count('1')
del category_ids[0:ones_last_index]
【讨论】:
让
>>> x = [1, 2, 3, 4, 2, 2, 3]
之前已经发布的最简单有效的解决方案是
>>> x[:] = [v for v in x if v != 2]
>>> x
[1, 3, 4, 3]
另一种应该使用较少内存但速度较慢的可能性是
>>> for i in range(len(x) - 1, -1, -1):
if x[i] == 2:
x.pop(i) # takes time ~ len(x) - i
>>> x
[1, 3, 4, 3]
10% 匹配条目的长度为 1000 和 100000 的列表的计时结果:0.16 vs 0.25 ms,以及 23 vs 123 ms。
【讨论】:
for i in range(a.count(' ')):
a.remove(' ')
我相信要简单得多。
【讨论】:
lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list():
for list in lists:
if(list!=7):
print(list)
remove_values_from_list()
结果:6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11
lists = [6.9,7,8.9,3,5,4.9,1,2.9,7,9,12.9,10.9,11,7]
def remove_values_from_list(remove):
for list in lists:
if(list!=remove):
print(list)
remove_values_from_list(7)
结果:6.9 8.9 3 5 4.9 1 2.9 9 12.9 10.9 11
【讨论】:
我只是为了一个列表而这样做的。我只是一个初学者。稍微高级一点的程序员肯定可以写出这样的函数。
for i in range(len(spam)):
spam.remove('cat')
if 'cat' not in spam:
print('All instances of ' + 'cat ' + 'have been removed')
break
【讨论】:
如果您没有内置 filter 或者不想使用额外的空间并且您需要线性解决方案...
def remove_all(A, v):
k = 0
n = len(A)
for i in range(n):
if A[i] != v:
A[k] = A[i]
k += 1
A = A[:k]
【讨论】:
hello = ['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd']
#chech every item for a match
for item in range(len(hello)-1):
if hello[item] == ' ':
#if there is a match, rebuild the list with the list before the item + the list after the item
hello = hello[:item] + hello [item + 1:]
print hello
['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
【讨论】:
我们也可以使用del 或pop 就地删除所有内容:
import random
def remove_values_from_list(lst, target):
if type(lst) != list:
return lst
i = 0
while i < len(lst):
if lst[i] == target:
lst.pop(i) # length decreased by 1 already
else:
i += 1
return lst
remove_values_from_list(None, 2)
remove_values_from_list([], 2)
remove_values_from_list([1, 2, 3, 4, 2, 2, 3], 2)
lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)], 2)
print(len(lst))
现在为了效率:
In [21]: %timeit -n1 -r1 x = random.randrange(0,10)
1 loop, best of 1: 43.5 us per loop
In [22]: %timeit -n1 -r1 lst = [random.randrange(0, 10) for x in range(1000000)]
g1 loop, best of 1: 660 ms per loop
In [23]: %timeit -n1 -r1 lst = remove_values_from_list([random.randrange(0, 10) for x in range(1000000)]
...: , random.randrange(0,10))
1 loop, best of 1: 11.5 s per loop
In [27]: %timeit -n1 -r1 x = random.randrange(0,10); lst = [a for a in [random.randrange(0, 10) for x in
...: range(1000000)] if x != a]
1 loop, best of 1: 710 ms per loop
正如我们所见,就地版本 remove_values_from_list() 不需要任何额外的内存,但它确实需要更多的时间来运行:
【讨论】:
没有人发布时间和空间复杂性的最佳答案,所以我想我会试一试。这是一个解决方案,它可以在不创建新数组的情况下以高效的时间复杂度删除所有出现的特定值。缺点是元素不保持顺序。
时间复杂度:O(n)
额外的空间复杂度:O(1)
def main():
test_case([1, 2, 3, 4, 2, 2, 3], 2) # [1, 3, 3, 4]
test_case([3, 3, 3], 3) # []
test_case([1, 1, 1], 3) # [1, 1, 1]
def test_case(test_val, remove_val):
remove_element_in_place(test_val, remove_val)
print(test_val)
def remove_element_in_place(my_list, remove_value):
length_my_list = len(my_list)
swap_idx = length_my_list - 1
for idx in range(length_my_list - 1, -1, -1):
if my_list[idx] == remove_value:
my_list[idx], my_list[swap_idx] = my_list[swap_idx], my_list[idx]
swap_idx -= 1
for pop_idx in range(length_my_list - swap_idx - 1):
my_list.pop() # O(1) operation
if __name__ == '__main__':
main()
【讨论】:
关于速度!
import time
s_time = time.time()
print 'start'
a = range(100000000)
del a[:]
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 3.25
s_time = time.time()
print 'start'
a = range(100000000)
a = []
print 'finished in %0.2f' % (time.time() - s_time)
# start
# finished in 2.11
【讨论】:
p=[2,3,4,4,4]
p.clear()
print(p)
[]
仅适用于 Python 3
【讨论】:
有什么问题:
Motor=['1','2','2']
For i in Motor:
If i != '2':
Print(i)
Print(motor)
使用蟒蛇
【讨论】: