3

I have a list that looks like:

a = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10']

I need to cycle through this list one element at a time but when the end of the list is reached, the cycle needs to be reversed.

For example, using itertools.cycle:

from itertools import cycle
a_cycle = cycle(a)
for _ in range(30):
    print a_cycle.next()

I get:

01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10

but what I need is:

01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 10, 09, 08, 07, 06, 05, 04, 03, 02, 01, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10

I need to cycle through a for a fixed number of times, say 200.

Gabriel
  • 40,504
  • 73
  • 230
  • 404
  • 1
    Do you need this to be indefinite? – NDevox May 29 '15 at 12:54
  • @ScironicI need it to run until an outer `for` loop (not shown in question) exhausts its elements. – Gabriel May 29 '15 at 12:57
  • Dimo414's solution should work, you can just cycle through that. – NDevox May 29 '15 at 12:59
  • 1
    That was me, sorry. I sloppily misread your code. Saw the `i in range(30)` and the leading zeros and thought you're among the many people not showing actual data. I undid the vote. Wouldn't have happened if you had written `for _ in range(30)`, btw, as that's the convention for values you're not going to use. But it was really my fault and I should take a break. – Stefan Pochmann May 29 '15 at 13:14
  • No worries, I removed the question about the downvote after realizing it was gone. I'll change `i` for `_`, thanks for the suggestion! – Gabriel May 29 '15 at 13:16

4 Answers4

11

You can cycle the chain of your a and reversed a, eg:

from itertools import cycle, islice, chain

a = range(1, 11)
b = reversed(a)
c = cycle(chain(a, b))
d = list(islice(c, 100)) # `c` is infinite - hence the `islice` to stop at some point...

Which gives you:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]

Note: If a is an exhaustable iterator, you will need to make a copy of a first. But given your example, this will be fine.

jesterjunk
  • 2,342
  • 22
  • 18
Jon Clements
  • 138,671
  • 33
  • 247
  • 280
3

Do you actually need to cycle through the list, as in go forward and backwards forever? Or just .reverse() the list?

print a + a[::-1]

Will do what you describe. The reversed() built-in also works, but you need to chain() it, as it returns an iterator, e.g.:

print list(itertools.chain(a, reversed(a)))

You can call itertools.cycle() on either result to get an infinite iterator of the list concatenated with its reverse.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • 1
    `.reverse()` doesn't return anything so wouldn't work. use `a+a[::-1]` instead – NDevox May 29 '15 at 12:55
  • @Scironic is correct, `a.reverse()` returns `None`. – Gabriel May 29 '15 at 12:56
  • your edit still doesn't work as lists are mutable, so assigning it to a new variable and reversing it reverses both lists. You would need to copy to do this, but it's easier to use a reverse slice – NDevox May 29 '15 at 12:58
2
def forwardback(lst):
    tot = len(lst)
    while 1:
        for i in xrange(tot):
            yield lst[i]
        for i in xrange(tot-1,-1,-1):
            yield lst[i]

or (using cycle's approach, which works for all iterators)

def forwardback(lst):
    saved = []
    for elem in lst:
        yield elem
        saved.append(elem)
    while saved:
        for elem in reversed(saved):
            yield elem
        for elem in saved:
            yield elem
shashwat
  • 992
  • 1
  • 13
  • 27
  • Note: `i` is not yet defined when you do `yield lst[i]` in your 2nd code block. And why use indices when you can directly iterate over iterables? You can use `reversed()` to do reverse iteration on any iterable, and extended slice notation on things like lists, eg `for v in reversed(saved):` or `for v in saved[::-1]:`. – PM 2Ring May 29 '15 at 13:57
  • Thanks. Fixed typo. Had copied previous program and edited it. Also, you're right about `reversed`. I wasn't aware it returned an iterator. I didn't want to use more space and re-recreate the list. – shashwat May 30 '15 at 07:41
2

Make a copy of list a, reverse it, then append it.

a = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10']
b = a[:]
b.reverse()
a = a + b

or based on a comment suggestion.

a = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10']
b = a[::-1]
a = a + b
Robert Jacobs
  • 3,266
  • 1
  • 20
  • 30