Python Traverse list reverse order

来源:互联网 发布:python find函数实现 编辑:程序博客网 时间:2024/06/05 22:37

Traverse a list in reverse order in Python

up vote252down votefavorite
50

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.

shareimprove this question
 

13 Answers

activeoldestvotes
up vote412down voteaccepted

Use the reversed() built-in function:

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

To also access the original index:

>>> for i, e in reversed(list(enumerate(a))):...     print i, e... 2 baz1 bar0 foo
shareimprove 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. SebastianFeb 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
up vote61down vote

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").

shareimprove 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 
up vote32down vote

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
shareimprove 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 
up vote15down vote

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)

shareimprove 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
up vote10down vote

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 itertoolsdef 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.

shareimprove this answer
 
up vote2down vote

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)]...4d3c2b1a>>>

OR

>>> length = len(foo)>>> for i in range(length):...     print foo[length-i-1]...4d3c2b1a>>>
shareimprove this answer
 
up vote1down vote

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

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

shareimprove this answer
 
up vote1down vote

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 ) ]
shareimprove this answer
 
up vote1down vote
def reverse(spam):    k = []    for i in spam:        k.insert(0,i)    return "".join(k)
shareimprove this answer
 
up vote1down vote
>>> l = ["a","b","c","d"]>>> l.reverse()>>> l['d', 'c', 'b', 'a']

OR

>>> print l[::-1]['d', 'c', 'b', 'a']
shareimprove this answer
0 0
原创粉丝点击