循环中的Python下一个迭代器

时间:2017-06-07 18:38:59

标签: python iterator

我有一个像这样的小例程:

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

3 个答案:

答案 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秒