代码之家  ›  专栏  ›  技术社区  ›  Tomas Lapsansky

跳回python迭代器

  •  0
  • Tomas Lapsansky  · 技术社区  · 7 年前

    像这样的C代码,最有效的方法是什么

    for(int i = 0; i < 10; i++) {
        printf("%d\n", i);
        if(i == 5)
            i = 1;
    }
    

    在python中,因此输出为

    0
    1
    2
    3
    4
    5
    1
    2
    3
    4
    5
    1
    

    我知道next()的范围内有for

    iterator = iter(range(0, 10))
    for i in iterator:
        next(iterator)
        print(i)
    

    所以这段代码会每秒打印一个数字,但我不知道如何跳回循环。

    4 回复  |  直到 7 年前
        1
  •  7
  •   Stephen Rauch Afsar Ali    7 年前

    您可以使用 itertools.cycle() 您可以使用 itertools.chain() 要附加起始条件,请执行以下操作:

    import itertools as it
    for i in it.chain((0,), it.cycle(range(1, 6))):
        print(i)
    

    结果:

    0
    1
    2
    3
    4
    5
    1
    2
    3
    4
    5
    
        2
  •  1
  •   Tomas Lapsansky    7 年前

    因此,我从评论中意识到,我必须以这样的方式使用while循环

    i = 0
    while i < 10:
        print(i)
        if i == 5:
            i = 1
    

    上面使用itertools和chain的例子很好,但我想要一些类似while cycle的解决方案,但我没有考虑while。在我的代码中,有一些更复杂的条件,不仅是这个简单的“链”,而且我认为它足以演示“跳跃”。

        3
  •  0
  •   Caputo    7 年前

    @Stephen我尝试不用链条,效果很好。thks nice代码

    import itertools as it
    for i in it.cycle(range(1, 6)):
        print(i)
    
        4
  •  0
  •   Alain T.    7 年前

    您可以使用迭代器类来复制大部分C风格的for循环。

    例如:

    class cFor:   
        def __init__(self,start,condition,step=1):
            self.index     = start
            self.nextIndex = start
            self.doLoop    = condition
            if type(condition) == type(start):
                self.doLoop  = lambda x:x < condition
            self.getNext   = step
            if type(step) == type(start):
                self.getNext = lambda x:x + step
    
        def __iter__(self):
            return self
    
        def next(self) : return self.__next__()
    
        def __next__(self):
            if self.doLoop(self.nextIndex):
                self.index     = self.nextIndex
                self.nextIndex = self.getNext(self.index)
                return self.index
            raise StopIteration()
    

    这将允许您执行简单的循环:

    for i in cFor(0,10,2) : print(i)
    # 0, 2, 4, 6, 8
    

    并且,使用lambdas,您可以提供自己的条件和增量计算:

    for i in cFor(1, lambda i:i<=10, lambda i:i+3): print(i)
    # 1, 4, 7, 10
    

    或应用更复杂的“内联”计算:

    [ a for a,b in cFor((1,1),lambda ab:ab[1]<30,lambda ab:(ab[1],sum(ab))) ]
    # [ 1, 1, 2, 3, 5, 8, 13 ]
    

    为了能够修改循环中的索引(或条件或增量),您可以创建一个生成器函数来返回当前索引和迭代器实例。这将允许您控制循环体中迭代器的属性。

    def cForLoop(start,condition,step=1):
        loop = cFor(start,condition,step)
        while True : yield loop.next(), loop
    
    for i,loop in cForLoop(0,10):
        print(i)
        if i == 5 : loop.nextIndex = 1
    # 0, 1, 2, 3, 4, 5, 1, 2, 3, 4, 5, ....
    

    例如,您可以使用它来实现一个简单的冒泡排序:

    arr = [3,7,4,2,8,1,6]
    
    for i,loop in cForLoop(1,len(arr)):
        if arr[i-1] > arr[i] :
            arr[i],arr[i-1] = arr[i-1],arr[i]
            loop.nextIndex = max(1,i-1) 
    
    # arr == [1, 2, 3, 4, 6, 7, 8]