Cycle around a sequence

Steven D'Aprano steve+comp.lang.python at pearwood.info
Thu Feb 9 04:55:30 CET 2012


On Wed, 08 Feb 2012 01:10:28 +0000, Mark Lawrence wrote:

> I'm looking at a way of cycling around a sequence i.e. starting at some
> given location in the middle of a sequence and running to the end before
> coming back to the beginning and running to the start place.

If you have a sequence, and don't mind copying it, the easiest way is 
just to slice and join:


>>> a = range(20)
>>> b = a[5:] + a[:5]
>>> print b
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4]

Short, sweet, easy and simple. What's not to like about it?

For small (say, less than a few thousand of items) sequences, this 
probably is the fastest way to do it. 

Handling this lazily is trickier than it seems, because you have to store 
the first N items somewhere until you get to the rest of the iterable. 
There is no Right Way to do it, since the best solution will depend on 
how many items you have and how large N is.

Here's one way with itertools:


>>> from itertools import islice, chain, tee
>>> a = iter(range(20))
>>> t1, t2 = tee(a)
>>> b = chain(islice(t1, 5, None), islice(t2, None, 5))
>>> print list(b)
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4]

But read the docs for tee first: it may be that converting to a list is 
faster and more memory efficient.

http://docs.python.org/library/itertools.html#itertools.tee


Using tee may be overkill. Here's a simpler way:

>>> a = iter(range(20))
>>> t = list(islice(a, 5))
>>> b = chain(a, t)
>>> list(b)
[5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 1, 2, 3, 4]

If your data is truly humongous, already stored in a list, and you don't 
want to make a copy, then I recommend your trick of generating the 
indexes:

def cycle(seq, n):
    for indexes in (xrange(n, len(seq)), xrange(n)):
        for i in indexes:
            yield seq[i]

If your data is humongous but only available lazily, buy more memory :)



-- 
Steven



More information about the Python-list mailing list