Tomas Lapsansky
Tomas Lapsansky

Reputation: 95

Jump back in python iterator

What's the most effective way to do something like this C code

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

in python, so the output would be

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

I know there is for in range with next()

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

so this code would print every second number, but I don't know how to jump back in for loop.

Upvotes: 0

Views: 1181

Answers (4)

Alain T.
Alain T.

Reputation: 42143

You can reproduce much of the C style for loop using an iterator class.

For example:

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()

This will allow you to perform simple loops:

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

and, using lambdas, you can provide your own condition and increment calculation:

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

or apply more complex "inline" calculations :

[ 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 ]

To be able to modify the index (or condition or increment) within the loop, you could create a generator function that returns both the current index and the iterator instance. This will let you take control of the iterator's properties within the loop body.

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, ....

you could, for example, use this to implement a simple bubble sort:

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]

Upvotes: 0

Tomas Lapsansky
Tomas Lapsansky

Reputation: 95

So I realize from the comments that I have to use while loop in the way like this

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

The example above with itertools and chain is nice, but I wanted some solution like this while cycle, but I wasn't thinking about while. In my code, there are some more complex conditions, not only this easy "chain", but I thought that it will be enough for a demonstration of "jump".

Upvotes: 1

Caputo
Caputo

Reputation: 1

@Stephen I try without chain and work well. thks nice code

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

Upvotes: 0

Stephen Rauch
Stephen Rauch

Reputation: 49794

You can loop forever using itertools.cycle() and you can use itertools.chain() to append the starting condition like:

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

Results:

0
1
2
3
4
5
1
2
3
4
5

Upvotes: 7

Related Questions