## Saturday, January 30, 2010

### Cycling along a list

This question on Stack Overflow involved the problem of moving along a list and then, once you reach the end, cycling back to the beginning. One very simple way to do that is to use the % (mod) operator. If the length of the list isn't changing (and it isn't a good idea to change a list during iteration), you can cache the length of the list:

 `>>> L = list('abcde')>>> N = len(L)>>> rL = list()>>> for i in range(12):... rL.append(L[i%N])... >>> print ''.join(rL)abcdeabcdeab`

Other answers used several functions from itertools:

 `from itertools import cycle`

We can check out the docs (remember)

 `\$ pydoc -w itertools`

 `>>> L = list('abcde')>>> it = cycle(L)>>> rL = list()>>> for i in range(12):... rL.append(it.next())... >>> print ' '.join(rL)a b c d e a b c d e a b`

To get the elements in groups of two (advancing one index at a time):

 `>>> it = cycle(L)>>> x = it.next()>>> for i in range(12):... y = it.next()... rL.append(x+y)... x = y... >>> print ' '.join(rL)ab bc cd de ea ab bc cd de ea ab bc`

Or, you can do a full itertools solution with the functions tee and izip as well as cycle.

`tee` makes two independent iterators for the sequence and `izip` zips them up (of course):

 `>>> from itertools import izip, cycle, tee>>>>>> def pairwise(seq):... a, b = tee(seq)... next(b)... return izip(a, b)... >>> L = list('abcde')>>> rL = list()>>> it = pairwise(cycle(L))>>> for i in range(12):... rL.append(''.join(it.next()))... >>> print ' '.join(rL)ab bc cd de ea ab bc cd de ea ab bc`

Or use `islice`:

 `>>> from itertools import islice>>> it = pairwise(cycle(L))>>> [''.join(t) for t in islice(it,6)]['ab', 'bc', 'cd', 'de', 'ea', 'ab']`