Python Traverse list reverse order

So I can start from len(collection) and end in collection[0].

EDIT: Sorry, I forgot to mention I also want to be able to access the loop index.

share improve this question
 

13 Answers

up vote 412 down vote accepted

Use the reversed() built-in function:

>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
...     print i
... 
baz
bar
foo

To also access the original index:

>>> for i, e in reversed(list(enumerate(a))):
...     print i, e
... 
2 baz
1 bar
0 foo
share improve this answer
 
32 
No copy is created, the elements are reversed on the fly while traversing! This is an important feature of all these iteration functions (which all end on “ed”). –  Konrad Rudolph  Feb 9 '09 at 19:10
5 
@Greg Hewgill No, it's an iterator over the original, no copy is created! –  André  Feb 9 '09 at 19:14
38 
To avoid the confusion: reversed() doesn't modify the list. reversed() doesn't make a copy of the list (otherwise it would require O(N) additional memory). If you need to modify the list use alist.reverse(); if you need a copy of the list in reversed order use alist[::-1]. –  J.F. Sebastian Feb 9 '09 at 19:27
31 
in this answer though, list(enumerate(a)) DOES create a copy. –  Triptych  Feb 9 '09 at 19:29
9 
@ JF, reversed() doesn't make a copy, but list(enumerate()) DOES make a copy. –  Triptych  Feb 9 '09 at 19:55

You can do:

for item in my_list[::-1]:
    print item

(Or whatever you want to do in the for loop.)

The [::-1] slice reverses the list in the for loop (but won't actually modify your list "permanently").

share improve this answer
 
7 
[::-1] creates a shallow copy, therefore it doesn't change the array neither "permanently" nor "temporary".–  J.F. Sebastian  Feb 9 '09 at 19:15
2 
This is slightly slower than using reversed, at least under Python 2.7 (tested). –  kgriffs  Jan 2 '14 at 16:49
 
This works for query objects, reversed() does not. Thanks!!! –  Roman  Jun 4 '14 at 11:30
 
How this answer works: It creates the temporary copy from a list slice which is an iteration of the list with the parameters: start point: unspecified (defaults to end of list - len(my_list)), end point: unspecified (defaults to start of list - 0) and step-1 (iterate backwards through the list, 1 item at a time) –  Edward  Nov 29 '15 at 16:48 

If you need the loop index, and don't want to traverse the entire list twice, or use extra memory, I'd write a generator. 

def reverse_enum(L):
   for index in reversed(xrange(len(L))):
      yield index, L[index]

L = ['foo', 'bar', 'bas']
for index, item in reverse_enum(L):
   print index, item
share improve this answer
 
 
I would call the function enumerate_reversed, but that might be only my taste. I believe your answer is the cleanest for the specific question. –  tzot  Feb 9 '09 at 20:58
1 
reversed(xrange(len(L))) produces the same indices as xrange(len(L)-1, -1, -1). –  J.F. Sebastian  Feb 10 '09 at 16:52
1 
I prefer fewer moving parts to understand: for index, item in enumerate(reversed(L)): print len(L)-1-index, item –  Don Kirkby  Nov 5 '14 at 21:56
1 
@Triptych I just had to cope with fact that enumerate from reversed() won't yield reversed indexes, and your code helped a lot. This method should be in the standard library. –  oski86  Jul 21 '15 at 18:57
1 
reversed(xrange()) works because an xrange object has the __reversed__ method as well as the __len__ and __getitem__ methods, and reversed can detect that and use them. But an enumerate object doesn't have __reversed__, __len__ or __getitem__. But why doesn't enumerate have them? I don't know that. –  FutureNerd  Sep 24 '15 at 1:01 

It can be done like this:

for i in range(len(collection)-1, -1, -1):
    print collection[i]

So your guess was pretty close :) A little awkward but it's basically saying: start with 1 less than len(collection), keep going until you get to just before -1, by steps of -1. 

Fyi, the help function is very useful as it lets you view the docs for something from the Python console, eg:

help(range)

share improve this answer
 
 
For versions of Python prior to 3.0, I believe xrange is preferable to range for large len(collection). –  Brian M. Hunt  Feb 9 '09 at 23:26
 
I believe you are correct :) iirc, range() generates the whole range as an array but xrange() returns an iterator that only generates the values as they are needed. –  Alan Rowarth  Feb 9 '09 at 23:57
5 
This just looks too weird with so many -1's. I would just say reversed(xrange(len(collection)))–  musiphil  Sep 7 '13 at 1:18

The reversed builtin function is handy:

for item in reversed(sequence):

The documentation for reversed explains its limitations.

For the cases where I have to walk a sequence in reverse along with the index (e.g. for in-place modifications changing the sequence length), I have this function defined an my codeutil module:

import itertools
def reversed_enumerate(sequence):
    return itertools.izip(
        reversed(xrange(len(sequence))),
        reversed(sequence),
    )

This one avoids creating a copy of the sequence. Obviously, the reversed limitations still apply.

share improve this answer
 

How about without recreating a new list, you can do by indexing:

>>> foo = ['1a','2b','3c','4d']
>>> for i in range(len(foo)):
...     print foo[-(i+1)]
...
4d
3c
2b
1a
>>>

OR

>>> length = len(foo)
>>> for i in range(length):
...     print foo[length-i-1]
...
4d
3c
2b
1a
>>>
share improve this answer
 

Use list.reverse() and then iterate as you normally would.

http://docs.python.org/tutorial/datastructures.html

share improve this answer
 

The other answers are good, but if you want to do as List comprehension style

collection = ['a','b','c']
[item for item in reversed( collection ) ]
share improve this answer
 
def reverse(spam):
    k = []
    for i in spam:
        k.insert(0,i)
    return "".join(k)
share improve this answer
 
>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']

OR

>>> print l[::-1]
['d', 'c', 'b', 'a']
share improve this answer
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值