reversed(enumerate(x))

Steven D'Aprano steve at pearwood.info
Wed Jul 20 15:13:18 EDT 2016


On Thu, 21 Jul 2016 03:46 am, Chris Angelico wrote:

> On Thu, Jul 21, 2016 at 3:42 AM, Ian Kelly <ian.g.kelly at gmail.com> wrote:
>> I had occasion to write something like this:
>>
>>     for i, n in reversed(enumerate(x)): pass
>>
>> Of course this fails with "TypeError: argument to reversed() must be a
>> sequence". I ended up using this instead:
>>
>>     for i, n in zip(reversed(range(len(x))), reversed(x)): pass
> 
> At the cost of coalescing the enumeration, you could:
> 
> for i, n in reversed(list(enumerate(x))): pass
> 
> It's reasonably clean but less efficient.


Less efficient than what? 

reversed() only operates on sequences, so it can't operate on arbitrary
iterators of unknown length? Possibly of indefinite length?

def iter():
    while random.random() > 0.01:
        yield random.random()

So in the most general case, you have to form a list before you can reverse
it.

Personally, I think your version is the most straightforward and obvious
solution that works on anything. (Well, perhaps not on infinite iterators.)
Yes, you have to convert x into a list, but that's in general the only way
to use reversed() anyway. If your needs are not too great, or simplicity of
code is more important than 

The "best" solution might be some more work: you might convert x into a list
only if it's an iterator, then iterate over it in reverse:


def sequencefy(x):
    if x is iter(x):
        return list(x)
    return x

def enumerate_down(it):
    seq = sequencefy(it)
    n = len(seq) - 1
    for item in reversed(seq):
        yield (n, item)
        n -= 1

for i, item = enumerate_down(x):
    ...



An advantage of this is that it works well with lazy sequences like
(x)range. There's no need to build up a huge list of (index, item) pairs
before reversing it.


-- 
Steven
“Cheer up,” they said, “things could be worse.” So I cheered up, and sure
enough, things got worse.




More information about the Python-list mailing list