tags:

views:

3648

answers:

7

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

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

+30  A: 

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
Greg Hewgill
Thanks. Out of curiosity, does this reversed method, creates a separate copy of the collection or just alters the looping?
Joan Venge
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
The reversed() function makes a copy of the collection. To modify an existing list, use the .reverse() method.
Greg Hewgill
@Greg Hewgill No, it's an iterator over the original, no copy is created!
André
Thanks Greg, it's awesome method.
Joan Venge
@André: you're right of course, but I was using the same words as the question asked by Joan, so that the answer would be more easily understood. Conceptually, it creates a copy. In implementation, it uses an iterator.
Greg Hewgill
@Greg: Your new chunk of code to access the original index creates a second copy of the original collection. It would be better just to do something like i = len(a) - 1 - ridx
Theran
Kinda sucks that this has to traverse the entire list before iteration... Still upvoted.
Triptych
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
in this answer though, list(enumerate(a)) DOES create a copy.
Triptych
It doesn't quite make a copy, it seems to do the same logic as manually walking backwards. If you call reversed, then alter the list, then iterate over the reversed list, the changes will be reflected by reversed().
Richard Levasseur
It absolutely makes a copy of the list. More accurately a zip of the list with it's positional indexes.
Triptych
@Triptych: `reversed([a,b,c])` does *not* create a copy of `[a, b, c]`.
J.F. Sebastian
I think there is some confusion here about exactly which example we're discussing. The first example only uses reversed(); the second example uses reversed(list(enumerate())). Clearly the second example makes more copies than the first. I think you're all correct on some level. :)
Greg Hewgill
@ JF, reversed() doesn't make a copy, but list(enumerate()) DOES make a copy.
Triptych
Thanks for the input guys, but seems like there is confusion about how these methods are implemented. By copy I meant, a deep copy, not an iterator. Iterators are fine but deep copies would slow my code considerable, for several millions of data.
Joan Venge
@Joan, you shouldn't be concerned with 'deep' versus 'shallow' copies. That only matters when you're dealing with nested lists. Even a 'shallow' copy will be expensive - it will duplicate the entire list. I believe my answer is the only one that matches your specs AND uses no extra memory.
Triptych
Thanks Triptych, that's what I mean, not collection copy but an iterator copy.
Joan Venge
+1  A: 

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

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

Bill Konrad
A: 

the reverse function comes in handy here:

myArray = [1,2,3,4]
myArray.reverse()
for x in myArray:
    print x
bchhun
list.reverse() has no return value
Georg
+10  A: 

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

mipadi
`[::-1]` creates a shallow copy, therefore it doesn't change the array neither "permanently" nor "temporary".
J.F. Sebastian
+10  A: 

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
Triptych
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.
ΤΖΩΤΖΙΟΥ
`reversed(xrange(len(L)))` produces the same indices as `xrange(len(L)-1, -1, -1)`.
J.F. Sebastian
@JF - yeah at the time I thought I had some reason for not doing it that way, but now I can't remember. Changing it now.
Triptych
A: 

Can it be done like so?:

for i in range (len(collection):0) :
    print collection[i]
Joan Venge
Greg's solution more pythonic.
epochwolf
Yes, but my question is would this work? Not style.
Joan Venge
Your syntax is wrong. : is used with [], not with arguments (such as for the range function). You could do: for i in range(len(collection)-1, -1, -1): print collection[i]. If you don't understand the arguments to range() there, check the tutorial and do some experimentation.
John Fouhy
+1  A: 

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)

Alan Rowarth
For versions of Python prior to 3.0, I believe xrange is preferable to range for large len(collection).
Brian M. Hunt
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