0

I am trying to reverse the same iterator several times, using the reversed function. For instance, with the code:

iterator = range(3)
N = 5
k = 0
out = []
while k < N:
    for i in iterator:
        out.append(i)
    iterator = reversed(iterator)
    k += 1
print(out)

I would want/expect to have the output:

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

But, after the first use of reverse, I get the error:

TypeError: 'range_iterator' object is not reversible

What could be an efficient workaround that does not require unpacking the iterator?

7
  • 1
    An iterator by definition cannot be reversed without unpacking. An iterator could be a generator, which just yields the next value at each step, which by definition isn't reversible. Commented Apr 7, 2021 at 10:03
  • I agree for a generator, but in this particular case for a range iterator, it would suffice to look at its start, stop, step attributes to build its reversed version without unpacking, wouldn't it? Commented Apr 7, 2021 at 10:07
  • And even if it needs to unpack it, I can be ok with that. The problem is, it lets me reverse it once, but then it does not let me reverse the already reversed iterator, which is basically going back to the original range iterator. Commented Apr 7, 2021 at 10:09
  • A range object is a special object which supports all sorts special iteration methods. Once you turn it into an actual iterator, that's gone. And since you're generically asking about iterators, it was worth pointing out that this isn't generalisable to iterators at all. Commented Apr 7, 2021 at 10:12
  • 1
    It doesn't "let you reverse it" once; it lets you create an iterator that iterates in reverse directly from the iterable. Commented Apr 7, 2021 at 10:17

2 Answers 2

1

You can simply alternate the original iterator and the reversed iterator. You can start with this simple example:

iterator = range(3)
N = 5
k = 0
out = []
while k < N:
    if k%2 == 0:
        it = iterator
    else:
        it = reversed(iterator)
    for i in it:
        out.append(i)
    k += 1
print(out)

[0, 1, 2, 2, 1, 0, 0, 1, 2, 2, 1, 0, 0, 1, 2]
Sign up to request clarification or add additional context in comments.

1 Comment

The if could be: it = iterator if k % 2 == 0 else reversed(iterator) or even: it = [iterator, reversed(iterator)][k % 2].
0

Thanks for all the replies. I knew beforehand that I could just do with a list containing both the original and the reversed version and just select the one I need, but really wanted to see if there was out there something that appears natural to me such as reversed(reversed(whatever)). So, making it a bit more compact, and adding a boolean do_reverse (which I need in my actual project) I will go with something like this:

iterator = range(3)
do_reverse = True
N = 5
k = 0
out = []
while k < N:
    for i in [iterator, reversed(iterator)][k % 2 * do_reverse]:
        out.append(i)
    k += 1
print(out)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.