How to iterate through list infinitely with +1 offset each loop

Question:

I want to infinitely iterate through the list from 0 to the end, but in the next loop I want to start at 1 to the end plus 0, and the next loop would start at 2 to the end plus 0, 1, up to the last item where it would start again at 0 and go to the end.

Here is my code:

a = [ 0, 1, 2 ]
offset = 0
rotate = 0

while True:
    print(a[rotate])
    offset += 1
    rotate += 1
    if offset >= len(a):
        offset = 0
        rotate += 1
    if rotate >= len(a):
        rotate = 0

This is the solution I came up with so far. It’s far from perfect.

The result that I want is:

0, 1, 2 # first iteration
1, 2, 0 # second iteration
2, 0, 1 # third iteration
0, 1, 2 # fourth iteration

and so on.

Asked By: Scrampus

||

Answers:

You can create the lists with offsets using list slicing, and then repeat them infinitely using itertools.cycle(). This computes all of the rotations exactly once, and then cycles through all of them:

from itertools import cycle, islice

lst = [0, 1, 2]
items = [lst[i:] + lst[:i] for i in range(len(lst))]
iterator = cycle(items)

for item in islice(iterator, 10):
    print(item)

The above approach is fast once you’ve gotten past the precomputation, but you may (depending on your use case) prefer an approach that does not have an upfront time/space cost. In that case, you can use a generator instead:

from itertools import cycle, islice

def rotate(lst):
    for offset in cycle(range(len(lst))):
        yield lst[offset:] + lst[:offset]

lst = [0, 1, 2]
for item in islice(rotate(lst), 10):
    print(item)

Both of these output:

[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]

These code snippets have been improved from a suggestion by wjandrea.

Answered By: BrokenBenchmark

Try this:

a = [0, 1, 2]

while True:
    print(*a, sep=', ')
    a.append(a[0])
    a.pop(0)

Output:

0, 1, 2
1, 2, 0
2, 0, 1
0, 1, 2
1, 2, 0
2, 0, 1
...

Or, pop returns the element removed, so it can be simplified

a = [0, 1, 2]

while True:
    print(*a, sep=', ')
    a.append(a.pop(0))

[Thanks ShadowRanger and Tomerikoo for improvement suggestions.]

Answered By: The Thonnu

Here you have another alternative using pointers:

a = [ 0, 1, 2 ]
i = 0
l = len(a)
while True:
  out = []
  for j in range(i, i+l):
    out.append(a[j%l])
  print(out)
  i=(i+1)%l

Output:

[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
[0, 1, 2]
[1, 2, 0]
[2, 0, 1]
Answered By: Cardstdani

You can use a deque which has a built-in and efficient rotate function (~O(1)):

>>> d = deque([0,1,2])
>>> for _ in range(10):
...     print(*d)
...     d.rotate(-1)  # negative -> rotate to the left
...
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2
1 2 0
2 0 1
0 1 2
Answered By: GACy20

Another option, using list slicing:

cycles = [a[i:]+a[:i] for i, _ in enumerate(a)]
while True:
    for c in cycles: print(c)

Or, if you don’t want to precalculate O(n^2) space for cycles, you can keep making the cycles afresh:

from itertools import count
n = len(a)
for i in count():
    j = i%n
    print(a[j:]+a[:j])
Answered By: J.G.
Categories: questions Tags:
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.