【发布时间】:2013-02-12 16:01:13
【问题描述】:
如果我有一个包含许多重复项的 python 列表,并且我想遍历每个项目,而不是重复项,最好使用一个集合(如set(mylist),或找到另一种创建方式没有重复的列表?我想只是循环遍历列表并检查重复项,但我认为这就是 set() 在初始化时所做的。
所以如果mylist = [3,1,5,2,4,4,1,4,2,5,1,3] 和我真的只想循环通过[1,2,3,4,5](顺序无关紧要),我应该使用set(mylist) 还是别的什么?
在最后一个示例中可以使用另一种方法,因为列表包含其最小值和最大值之间的每个整数,我可以循环遍历range(min(mylist),max(mylist)) 或set(mylist)。在这种情况下,我通常应该尽量避免使用 set 吗?另外,查找min 和max 会比创建set 慢吗?
在最后一个例子中,set 更快:
from numpy.random import random_integers
ids = random_integers(1e3,size=1e6)
def set_loop(mylist):
idlist = []
for id in set(mylist):
idlist.append(id)
return idlist
def list_loop(mylist):
idlist = []
for id in range(min(mylist),max(mylist)):
idlist.append(id)
return idlist
%timeit set_loop(ids)
#1 loops, best of 3: 232 ms per loop
%timeit list_loop(ids)
#1 loops, best of 3: 408 ms per loop
【问题讨论】:
-
您是否认为这种速度差异在您编写的任何程序中真正重要?将内容保存在
numpy中,使用 genexp 而不是构建一百万个元素list只是为了迭代(如果这是 Py2,则使用xrange而不是range),尝试在 C 中进行紧密循环Python(例如,idlist = range(…)而不是做同样事情的for循环)等都会使数量级的差异更大。 -
更具体地说:
set_loop的整个主体相当于return list(set(mylist)),list_loop在 2.x 中相当于return range(min(mylist), max(mylist)),在 3.x 中相当于return list(range(min(mylist), max(mylist)))。更简单的版本可能会或可能不会明显更快,但它们永远不会更慢,而且它们更容易阅读。 -
您是否关心删除副本后列表是否保持相同的顺序?
-
@thewolf 顺序无关紧要,这就是我考虑设置的原因。
-
@askewchan:真的,你最好先写最易读的东西。如果您想要具有
set语义的东西,请使用set。如果程序结果很慢,并且分析显示构建或使用set是相关的,那么您可以寻找更快的解决方案。但是,如果您开始询问在程序中执行每个单独步骤的最快方法……那么,您应该用汇编而不是 Python 编写。