如何在Python中反向遍历列表?所以我可以从集合[len(collection)-1]开始,到集合[0]结束。

我还希望能够访问循环索引。


当前回答

假设任务是在列表中找到最后一个满足某些条件的元素(即向后看时的第一个元素),我得到以下数字。

Python 2:

>>> min(timeit.repeat('for i in xrange(len(xs)-1,-1,-1):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.6937971115112305
>>> min(timeit.repeat('for i in reversed(xrange(0, len(xs))):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
4.809093952178955
>>> min(timeit.repeat('for i, x in enumerate(reversed(xs), 1):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
4.931743860244751
>>> min(timeit.repeat('for i, x in enumerate(xs[::-1]):\n    if 128 == x: break', setup='xs, n = range(256), 0', repeat=8))
5.548468112945557
>>> min(timeit.repeat('for i in xrange(len(xs), 0, -1):\n    if 128 == xs[i - 1]: break', setup='xs, n = range(256), 0', repeat=8))
6.286104917526245
>>> min(timeit.repeat('i = len(xs)\nwhile 0 < i:\n    i -= 1\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', repeat=8))
8.384078979492188

所以,最丑的选项xrange(len(xs)-1,-1,-1)是最快的。

Python 3(不同机器):

>>> timeit.timeit('for i in range(len(xs)-1,-1,-1):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', number=400000)
4.48873088900001
>>> timeit.timeit('for i in reversed(range(0, len(xs))):\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', number=400000)
4.540959084000008
>>> timeit.timeit('for i, x in enumerate(reversed(xs), 1):\n    if 128 == x: break', setup='xs, n = range(256), 0', number=400000)
1.9069805409999958
>>> timeit.timeit('for i, x in enumerate(xs[::-1]):\n    if 128 == x: break', setup='xs, n = range(256), 0', number=400000)
2.960720073999994
>>> timeit.timeit('for i in range(len(xs), 0, -1):\n    if 128 == xs[i - 1]: break', setup='xs, n = range(256), 0', number=400000)
5.316207007999992
>>> timeit.timeit('i = len(xs)\nwhile 0 < i:\n    i -= 1\n    if 128 == xs[i]: break', setup='xs, n = range(256), 0', number=400000)
5.802550058999998

这里,enumerate(reversed(xs), 1)是最快的。

其他回答

你可以在一个普通的for循环中使用一个负索引:

>>> collection = ["ham", "spam", "eggs", "baked beans"]
>>> for i in range(1, len(collection) + 1):
...     print(collection[-i])
... 
baked beans
eggs
spam
ham

要访问索引,就像在集合的反向副本上向前迭代一样,使用i - 1:

>>> for i in range(1, len(collection) + 1):
...     print(i-1, collection[-i])
... 
0 baked beans
1 eggs
2 spam
3 ham

要访问未反转的原始索引,使用len(collection) - i:

>>> for i in range(1, len(collection) + 1):
...     print(len(collection)-i, collection[-i])
... 
3 baked beans
2 eggs
1 spam
0 ham

如果你需要索引,而你的列表很小,最易读的方法是像公认的答案所说的那样做reversed(list(enumerate(your_list))。但这将创建列表的副本,因此如果列表占用了很大一部分内存,则必须从len()-1中减去enumerate(reversed())返回的下索引。

如果你只需要做一次:

a = ['b', 'd', 'c', 'a']

for index, value in enumerate(reversed(a)):
    index = len(a)-1 - index

    do_something(index, value)

或者如果你需要多次这样做,你应该使用生成器:

def enumerate_reversed(lyst):
    for index, value in enumerate(reversed(lyst)):
        index = len(lyst)-1 - index
        yield index, value

for index, value in enumerate_reversed(a):
    do_something(index, value)

如果你需要循环索引,并且不想遍历整个列表两次,或者使用额外的内存,我会写一个生成器。

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

你可以:

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

(或者你想在for循环中做的任何事情。)

[::-1]片在for循环中反转列表(但实际上不会“永久”修改列表)。

可以这样做:

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

    # print(collection[i]) for python 3. +

所以你的猜测很接近:)有点尴尬,但它基本上是说:从小于len(collection)的1开始,一直到-1之前,一步一步到-1。

仅供参考,帮助函数非常有用,因为它可以让你从Python控制台查看文档,例如:

帮助(范围)