在Python中以相反的顺序遍历列表

Joa*_*nge 644 python reverse loops

所以我可以从头开始len(collection)并结束collection[0].

编辑:对不起,我忘了提到我也希望能够访问循环索引.

Gre*_*ill 1080

使用内置reversed()功能:

>>> a = ["foo", "bar", "baz"]
>>> for i in reversed(a):
...     print(i)
... 
baz
bar
foo
Run Code Online (Sandbox Code Playgroud)

要访问原始索引:

>>> for i, e in reversed(list(enumerate(a))):
...     print(i, e)
... 
2 baz
1 bar
0 foo
Run Code Online (Sandbox Code Playgroud)

  • 没有创建副本,元素在遍历时即时反转!这是所有这些迭代函数的重要特征(所有这些函数都以"ed"结尾). (122认同)
  • 为了避免混淆:`reversed()`不修改列表.`reversed()`不会复制列表(否则需要额外的O(N)内存).如果需要修改列表,请使用`alist.reverse()`; 如果你需要反向顺序的列表副本,请使用`alist [:: - 1]`. (87认同)
  • 在这个答案中,list(enumerate(a))可以创建一个副本. (82认同)
  • @ JF,reversed()不会复制,但list(enumerate())会复制. (38认同)
  • @Greg Hewgill不,它是原始的迭代器,没有创建副本! (9认同)
  • @Bill我认为`枚举(反转(a))`也是一种解决方案.但是,索引将按相反的顺序排列,即最后一个元素的索引为"0" (4认同)
  • 它绝对是列表的副本.更准确地说是列表的zip和它的位置索引. (3认同)
  • 我认为这里确实存在一些混淆,我们正在讨论哪个例子.第一个例子只使用reversed(); 第二个例子使用reverse(list(enumerate())).显然,第二个例子比第一个例子更多.我认为你在某种程度上都是正确的.:) (3认同)
  • @Greg:您访问原始索引的新代码块会创建原始集合的第二个副本.做一些像i = len(a) - 1 - ridx这样的事情会更好 (2认同)
  • 有点糟糕,这必须在迭代之前遍历整个列表......仍然投票。 (2认同)

mip*_*adi 155

你可以做:

for item in my_list[::-1]:
    print item
Run Code Online (Sandbox Code Playgroud)

(或者你想在for循环中做什么.)

[::-1]切片反转for循环在列表中(但不会实际修改列表的"永久").

  • `[:: - 1]`创建一个浅拷贝,因此它既不会"永久"也不会"临时"更改数组. (21认同)
  • **这个答案如何工作**:它创建一个带有参数的列表的切片副本:*起始点*:未指定(变为列表长度,因此从结束开始),*结束点*:未指定(变成一些幻数其他比"0",可能是"-1",所以在开始时结束)和*step*:`-1`(一次向后遍历列表,"1"项). (13认同)
  • 这比使用reverse略慢,至少在Python 2.7(测试版)下. (6认同)
  • 我也测试了这个(python 2.7),使用 [::-1] 与 `reversed()` 相比慢了约 10% (2认同)

Tri*_*ych 64

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

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
Run Code Online (Sandbox Code Playgroud)

  • 我会调用函数 enumerate_reversed,但这可能只是我的口味。我相信您的回答对于特定问题是最清晰的。 (3认同)
  • 我更喜欢更少的运动部件来理解:`对于索引,枚举项(反向(L)):打印len(L)-1-索引,项目` (2认同)
  • @Triptych我只需要处理从reverse()枚举的事实不会产生反转索引的事实,并且你的代码帮了很多.此方法应位于标准库中. (2认同)
  • reverse(xrange())有效,因为xrange对象具有\ _\__verse\_ _ _方法以及\ _\_ _ _ _ _ _ _ _ _和_ _\_ _ _ getitem\_\_ _方法,并且反向可以检测到并使用它们.但是枚举对象没有\ _\__verse\_ _ _,\ _ _ _ len\_\_ _或_ _\_ _ getitem\_\_ _.但是*为什么*没有列举它们?我不知道. (2认同)

小智 58

它可以这样做:

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

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

所以你的猜测非常接近:)有点尴尬,但它基本上是这样说:从1开始不到len(collection),继续前进直到-1到-1之前,步长为-1.

Fyi,该help函数非常有用,因为它允许您从Python控制台查看某些文档,例如:

help(range)

  • 对于那么多`-1`来说,这看起来太奇怪了.我只想说'逆转(xrange(len(collection)))` (11认同)
  • 对于 3.0 之前的 Python 版本,我相信 xrange 比大型 len(collection) 的范围更可取。 (2认同)

tzo*_*zot 22

reversed内置功能非常方便:

for item in reversed(sequence):
Run Code Online (Sandbox Code Playgroud)

文档的逆转说明了它的局限性.

对于我必须与索引一起反向遍历序列的情况(例如,对于更改序列长度的就地修改),我将此函数定义为我的codeutil模块:

import itertools
def reversed_enumerate(sequence):
    return itertools.izip(
        reversed(xrange(len(sequence))),
        reversed(sequence),
    )
Run Code Online (Sandbox Code Playgroud)

这个避免了创建序列的副本.显然,这些reversed限制仍然适用.


kso*_*all 20

没有导入的方法:

for i in range(1,len(arr)+1):
    print(arr[-i])
Run Code Online (Sandbox Code Playgroud)

或者

for i in arr[::-1]:
    print(i)
Run Code Online (Sandbox Code Playgroud)

  • 这个答案应该是最上面的,第一种方法使列表保持完整,不复制,我们只是向后移动索引。非常快。第二种方法将创建一个新列表,因此请注意。 (3认同)

Fre*_*ddy 9

>>> l = ["a","b","c","d"]
>>> l.reverse()
>>> l
['d', 'c', 'b', 'a']
Run Code Online (Sandbox Code Playgroud)

要么

>>> print l[::-1]
['d', 'c', 'b', 'a']
Run Code Online (Sandbox Code Playgroud)


X''*_*X'' 9

在 python 3 中,列表创建了一个副本,因此reversed(list(enumerate(collection))效率可能很低,生成的另一个列表没有被优化掉。

如果集合肯定是一个列表,那么最好将复杂性隐藏在迭代器后面

def reversed_enumerate(collection: list):
    for i in range(len(collection)-1, -1, -1):
        yield i, collection[i]
Run Code Online (Sandbox Code Playgroud)

所以,最干净的是:

for i, elem in reversed_enumerate(['foo', 'bar', 'baz']):
    print(i, elem)
Run Code Online (Sandbox Code Playgroud)


emo*_*hus 7

不管它的价值如何,你也可以这样做。很简单。

a = [1, 2, 3, 4, 5, 6, 7]
for x in xrange(len(a)):
    x += 1
    print a[-x]
Run Code Online (Sandbox Code Playgroud)

  • 您还可以执行“print a[-(x+1)]”并避免在循环体中重新分配索引。 (2认同)

Jam*_*pam 6

如果不重新创建新列表,可以通过索引来完成:

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

要么

>>> length = len(foo)
>>> for i in range(length):
...     print foo[length-i-1]
...
4d
3c
2b
1a
>>>
Run Code Online (Sandbox Code Playgroud)


小智 6

def reverse(spam):
    k = []
    for i in spam:
        k.insert(0,i)
    return "".join(k)
Run Code Online (Sandbox Code Playgroud)


lkr*_*der 6

我喜欢单线发电机的方法:

((i, sequence[i]) for i in reversed(xrange(len(sequence))))
Run Code Online (Sandbox Code Playgroud)


dis*_*oqi 6

另外,您可以使用“范围”或“计数”功能。如下:

a = ["foo", "bar", "baz"]
for i in range(len(a)-1, -1, -1):
    print(i, a[i])

3 baz
2 bar
1 foo
Run Code Online (Sandbox Code Playgroud)

您还可以按以下方式使用itertools中的“ count”:

a = ["foo", "bar", "baz"]
from itertools import count, takewhile

def larger_than_0(x):
    return x > 0

for x in takewhile(larger_than_0, count(3, -1)):
    print(x, a[x-1])

3 baz
2 bar
1 foo
Run Code Online (Sandbox Code Playgroud)


小智 5

list.reverse()照常使用,然后进行迭代。

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


小智 5

如果您需要索引并且列表很小,那么最易读的方法是reversed(list(enumerate(your_list)))按照接受的答案进行操作。但这会创建列表的副本,因此如果列表占用了大部分内存,则必须减去enumerate(reversed())from返回的索引len()-1

如果您只需要执行一次:

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

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

    do_something(index, value)
Run Code Online (Sandbox Code Playgroud)

或者如果您需要多次执行此操作,您应该使用生成器:

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)
Run Code Online (Sandbox Code Playgroud)


won*_*ice 5

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

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
Run Code Online (Sandbox Code Playgroud)

所以,最丑陋的选择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
Run Code Online (Sandbox Code Playgroud)

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