我有一个像这样的小例程:
to_use = [True] * n
val = 0
while (val is not None) :
# various manipulations on val
# so the val below is different from
# val entering the loop
to_use[val] = False
val = next((i for i in range(n) if to_use[i]),None)
在我的示例中,n
大约为一毫安。最后一个与迭代器相似的是获得下一个" val
"?的最有效方法。或者每次循环时它会从to_use
经过0
吗?请注意,to_use[i]=False
后,它永远不会重置为True
。
答案 0 :(得分:0)
我建议一次循环一个项目并将其从True更改为False:
在Python 2中:
for i in xrange(len(to_use)):
to_use[i] = False
在Python 3中:
for i in range(len(to_use)):
to_use[i] = False
Python 2中的xrange和Python 3中的范围是迭代器,因此您不会创建列表[0..len(n)]。
答案 1 :(得分:0)
另一种方法是将to_use
改为set
值:
to_use = set(range(n))
while len(to_use) > 0:
val = min(to_use)
# val manipulation here
to_use.remove(val)
请注意,此方法需要在每次迭代时扫描所有剩余值。平均而言,每次迭代,它会扫描n/2
个值。您的原始方法可能比该方法更快或更慢,具体取决于列表中的哪些元素按哪种顺序设置为False
。 (如果您倾向于从列表末尾将事物设置为False
,那么您的方法可能已经更快。如果您倾向于从列表的开头将事物设置为False
,那么{{1方法可能会更快。)
答案 2 :(得分:0)
感谢smarx在问题发表后的评论,我能够解决这个问题。每次调用它时,迭代器将在to_use
中经历数百万个条目。因为我知道to_use
条目在设置为False
后没有改变,所以我写了一个显式循环,跟踪前一个循环停止的位置,并从那里开始搜索。
val = next((i for i in range(n) if to_use[i]),None)
cProfile显示整个代码的208秒,其中大部分来自此行:
900811 function calls in 208.227 seconds
ncalls tottime percall cumtime percall filename:lineno(function)
199599 207.427 0.001 207.427 0.001 toposort.py:43(<genexpr>)
明确的电话
start = 0
to_use = [True] * n
val = 0
while (val is not None) :
# various manipulations on val
# so the val below is different from
# val entering the loop
to_use[val] = False
val = None
for i in range(start,n):
if to_use[i]:
val = i
start = i
break
cProfile显示整个代码
的0.513秒