0

假设您有一个包含n个条目的列表。此列表不包含统一数据(一些条目可能是字符串、其他整数,甚至其他列表)。假设该列表至少包含一个给定值的实例,那么删除该列表中所有实例的最快速度是多少?

我可以想到两个,一个列表理解,或者.remove()

  1. [item for item in lst if item != itemToExclude]
  2. for i in range(lst.count(itemToExclude)): lst.remove(itemToExclude)

但是对于任意大的列表,或者是否有任何其他方法,我不知道其中哪一个是最快的。作为旁注,如果有人可以提供一些指导方针来确定方法的速度,我将不胜感激!

4

4 回答 4

3

一般来说,您的方法1.会更快,因为它只在 C 代码中迭代列表一次。第二种方法首先遍历调用的列表,每次被调用时都lst.count从头开始迭代!lst.remove

要测量这些东西,请使用timeit

还值得一提的是,您提出的两种方法做的事情略有不同:

[item for item in lst if item != itemToExclude]

这将创建一个新列表。

for i in range(lst.count(itemToExclude)): lst.remove(itemToExclude)

这会修改现有列表。

于 2013-11-13T22:09:46.903 回答
1

您的第二个解决方案比您的第一个解决方案效率低得多。 count并且remove都遍历列表,因此要删除一个项目的 N 个副本,您必须遍历列表 N+1 次。而列表推导式只遍历列表一次,无论有多少副本。

于 2013-11-13T22:05:12.990 回答
0

测试.py:

lst = range(100) * 100
itemToExclude = 1

def do_nothing(lst):
    return lst

def listcomp(lst):
    return [item for item in lst if item != itemToExclude]

def listgenerator(lst):
    return list(item for item in lst if item != itemToExclude)

def remove(lst):
    for i in range(lst.count(itemToExclude)):
        lst.remove(itemToExclude)

def filter_lambda(lst):
    return filter(lambda x: x != itemToExclude, lst)

import operator
import functools

def filter_functools(lst):
    return filter(functools.partial(operator.ne, itemToExclude), lst)

lstcopy = list(lst)
remove(lstcopy)
assert(lstcopy == listcomp(list(lst)))
assert(lstcopy == listgenerator(list(lst)))
assert(lstcopy == filter_lambda(list(lst)))
assert(lstcopy == filter_functools(list(lst)))

结果:

$ python -mtimeit "import test; test.do_nothing(list(test.lst))"
10000 loops, best of 3: 26.9 usec per loop

$ python -mtimeit "import test; test.listcomp(list(test.lst))"
1000 loops, best of 3: 686 usec per loop

$ python -mtimeit "import test; test.listgenerator(list(test.lst))"
1000 loops, best of 3: 737 usec per loop

$ python -mtimeit "import test; test.remove(list(test.lst))"
100 loops, best of 3: 8.94 msec per loop

$ python -mtimeit "import test; test.filter_lambda(list(test.lst))"
1000 loops, best of 3: 994 usec per loop

$ python -mtimeit "import test; test.filter_functools(list(test.lst))"
1000 loops, best of 3: 815 usec per loop

所以remove会失败,但其余部分非常相似:列表理解可能超过filter. 显然,您可以对输入大小、已删除项目的数量和要删除的项目类型执行相同的操作,这些都更能代表您的实际预期用途。

于 2013-11-14T09:03:09.817 回答
0

试试这个:

filter(lambda x: x != itemToExclude, lst)

这里没有 Python 级别的循环——循环遍历数据一次,是“以 C 速度”完成的(嗯,在 CPython 中,是“通常的”实现)。

于 2013-11-13T22:32:32.993 回答