Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I reverse an itertools.chain object?

My function creates a chain of generators:

def bar(num):
    import itertools
    some_sequence = (x*1.5 for x in range(num))
    some_other_sequence = (x*2.6 for x in range(num))
    chained = itertools.chain(some_sequence, some_other_sequence)
    return chained

My function sometimes needs to return chained in reversed order. Conceptually, the following is what I would like to be able to do:

if num < 0:
    return reversed(chained)
return chained

Unfortunately:

>>> reversed(chained)
TypeError: argument to reversed() must be a sequence

What are my options?

This is in some realtime graphic rendering code so I don't want to make it too complicated/slow.

EDIT: When I first posed this question I hadn't thought about the reversibility of generators. As many have pointed out, generators can't be reversed.

I do in fact want to reverse the flattened contents of the chain; not just the order of the generators.

Based on the responses, there is no single call I can use to reverse an itertools.chain, so I think the only solution here is to use a list, at least for the reverse case, and perhaps for both.

like image 641
Steven T. Snyder Avatar asked Feb 15 '11 20:02

Steven T. Snyder


2 Answers

if num < 0:
    lst = list(chained)
    lst.reverse()
    return lst
else:
    return chained

reversed() needs an actual sequence, because it iterates it backwards by index, and that wouldn't work for a generator (which only has the notion of "next" item).

Since you will need to unroll the whole generator anyway for reversing, the most efficient way is to read it to a list and reverse the list in-place with the .reverse() method.

like image 166
shang Avatar answered Oct 07 '22 01:10

shang


You cannot reverse generators by definition. The interface of a generator is the iterator, which is a container that supports only forward iteration. When you want to reverse a iterator, you have to collect all it's items first and reverse them after that.

Use lists instead or generate the sequences backwards from the start.

like image 39
Jochen Ritzel Avatar answered Oct 07 '22 00:10

Jochen Ritzel