如何在Python中反转列表?

Leo*_*eis 947 python list

如何在Python中执行以下操作?

array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)
Run Code Online (Sandbox Code Playgroud)

我需要有一个数组的元素,但从最后到开头.

cod*_*ict 1221

您可以将此reversed功能用作:

>>> array=[0,10,20,40]
>>> for i in reversed(array):
...     print(i)
Run Code Online (Sandbox Code Playgroud)

请注意,reversed(...)不会返回列表.你可以使用反转列表list(reversed(array)).

  • 你不能只使用:array [:: - 1]? (165认同)
  • @kdlannoy根据链接到答案的页面,"与扩展切片相比,例如range(1,4)[:: - 1],reverse()更容易阅读,运行速度更快,并且使用的内存更少. " (119认同)
  • 为什么使用`reversed()`而不是切片?阅读Python的Zen,规则7:可读性很重要! (8认同)
  • 值得注意的是,这不是*与反向([1,2,3])相同,而是在末尾的'd'...这是下面的其他答案之一,这就是这样做的,而这会返回一个迭代器. (3认同)
  • 为避免混淆,您不应使用数组,因为此对象是一个列表对象。 (3认同)
  • 当我测试时,切片速度大约是以前的两倍(反转10k元素列表并从中创建列表时)。我没有测试内存消耗。但是,如果您以后无需强制转换为列表,则`reverse`可能会更快。 (2认同)
  • 这个答案底部的列表与迭代器注释对于Python新手(像我一样!)来说非常重要,因为当我在循环中使用反向列表并且不知道单次使用的行为时,它让我陷入了困境。迭代器(请参阅/sf/ask/1773570851/) (2认同)

ber*_*nie 1187

>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]
Run Code Online (Sandbox Code Playgroud)

扩展切片语法在Python 什么是新版本的条目中得到了很好的解释2.3.5

根据评论中的特殊要求,这是最新的切片文档.

  • @lunixbochs reverse返回迭代器而不是Python 3中的列表. (11认同)
  • 它适用于任何可交互的,而不仅仅是列表.缺点是它不到位. (8认同)
  • @Swiss对,但OP的例子是迭代:) (5认同)
  • @Tim它返回一个切片,因此不会改变实际的列表内容 (3认同)
  • @Swiss 并非在每个可迭代中,例如,“set”是可迭代的,但不可下标。 (3认同)
  • 除非在阵列中自然地正确封装 (2认同)
  • 我同意@Swiss.+1,因为问题是_I需要有一个数组的元素但是从结尾到开始._ - `reversed`返回一个`listreverseiterator`对象(Python 2.7.x),然后必须通过反向切片进行迭代返回一个反向列表/ tuple/str(取决于你正在切片的内容).@Einar Petersen正在反转一个字符串,所以输出是正确的.试试:`co2 = ['ae','ad','ac','ab','aa','z','y','x','w','v','u', 'T', 'S', 'R', 'q', 'p', '0', 'N', 'M', 'L', 'K', 'J', 'I',1 H ','g','f','e','d','c','b','a'] >>> co2 [:: - 1]` (2认同)

gho*_*g74 350

>>> L = [0,10,20,40]
>>> L.reverse()
>>> L
[40, 20, 10, 0]
Run Code Online (Sandbox Code Playgroud)

要么

>>> L[::-1]
[40, 20, 10, 0]
Run Code Online (Sandbox Code Playgroud)

  • [开始:停止:步骤]所以步骤为-1 (59认同)
  • 细节:第一个就地修改列表,第二个只返回一个新的反转列表,但它不会修改原始列表. (33认同)
  • 第二个例子应该是'L = L [:: - 1]`来实际反转列表,否则你只是反向返回值 (7认同)
  • 第二个像魔术一样工作,你能解释一下语法吗? (6认同)

fah*_*had 50

这是为了复制列表:

L = [0,10,20,40]
p = L[::-1]  #  Here p will be having reversed list
Run Code Online (Sandbox Code Playgroud)

这是为了反转列表:

L.reverse() # Here L will be reversed in-place (no new list made)
Run Code Online (Sandbox Code Playgroud)


pro*_*lob 48

我认为在Python中反转列表的最佳方法是:

a = [1,2,3,4]
a = a[::-1]
print(a)
>>> [4,3,2,1]
Run Code Online (Sandbox Code Playgroud)

工作完成了,现在你有一个反向列表.


Lig*_*tCC 31

带有解释和计时结果的方法总结

有三种不同的内置方法来反转列表。哪种方法最好取决于您是否需要:

  1. 就地反转现有列表(更改原始列表变量)
    • 最好的解决办法是object.reverse()方法
  2. 创建反向列表的迭代器(因为您要将其提供给 for 循环、生成器等)
    • 最好的解决方案是reversed(object)创建迭代器
  3. 以相反的顺序创建列表的副本(以保留原始列表)
    • 最佳解决方案是使用步长为 -1 的切片: object[::-1]

从速度的角度来看,最好使用内置函数来反转列表。在这种情况下,与手动创建的循环或生成器相比,它们在短列表(10 个项目)上快 2 到 8 倍,在长列表上快约 300 多倍。这是有道理的,因为它们是用母语(即 C)编写的,有专家创建、审查和优化。它们也不太容易出现缺陷,并且更有可能处理边缘和角落情况。

测试脚本

将本答案中的所有代码片段放在一起以制作一个脚本,该脚本将运行下面描述的反转列表的不同方式。它将在运行 100,000 次时为每个方法计时。长度为 2、10 和 1000 项的列表的结果显示在最后一部分。

from timeit import timeit
from copy import copy

def time_str_ms(t):
    return '{0:8.2f} ms'.format(t * 1000)
Run Code Online (Sandbox Code Playgroud)

方法一:用obj.reverse()原地反转

如果目标只是颠倒现有列表中项目的顺序,而不是遍历它们或获取要使用的副本,请使用该<list>.reverse()函数。直接在列表对象上运行这个,所有项目的顺序将被颠倒:

请注意,以下将反转给定的原始变量,即使它也返回反转的列表。即您可以使用此函数输出创建副本。通常,您不会为此创建函数,但计时脚本需要它。

我们测试这两种方式的性能 - 首先只是就地反转列表(更改原始列表),然后复制列表并在之后反转它,看看与其他方式相比,这是否是创建反转副本的最快方法方法。

def rev_in_place(mylist):
    mylist.reverse()
    return mylist

def rev_copy_reverse(mylist):
    a = copy(mylist)
    a.reverse()
    return a
Run Code Online (Sandbox Code Playgroud)

方法 2:使用切片反转列表 obj[::-1]

内置索引切片方法允许您制作任何索引对象的一部分的副本。

  • 它不影响原始对象
  • 它构建了一个完整的列表,而不是一个迭代器

通用语法是:<object>[first_index:last_index:step]. 为了利用切片创建一个简单的反向列表,使用:<list>[::-1]。当一个选项留空时,它将它们设置为对象的第一个和最后一个元素的默认值(如果步长为负,则相反)。

索引允许使用负数,从对象索引的末尾向后计数(即 -2 是倒数第二个项目)。当步长为负数时,它将从最后一个项目开始,并按该数量向后索引。

def rev_slice(mylist):
    a = mylist[::-1]
    return a
Run Code Online (Sandbox Code Playgroud)

方法三:用reversed(obj)迭代器函数反转一个列表

有一个reversed(indexed_object)功能:

  • 这将创建一个反向索引迭代器,而不是一个列表。如果您将其送入循环以在大型列表上获得更好的性能,那就太好了
  • 这会创建一个副本并且不会影响原始对象

使用原始迭代器进行测试,并从迭代器创建一个列表。

def reversed_iterator(mylist):
    a = reversed(mylist)
    return a

def reversed_with_list(mylist):
    a = list(reversed(mylist))
    return a
Run Code Online (Sandbox Code Playgroud)

方法 4:使用自定义/手动索引反向列表

正如时间所示,创建自己的索引方法是一个坏主意。除非您确实需要做一些自定义的事情,否则请使用内置方法。这只是意味着学习内置方法。

也就是说,较小的列表大小不会带来巨大的损失,但是当您扩大规模时,损失会变得巨大。我敢肯定,下面的代码可以优化,但它永远无法匹配内置方法,因为它们是直接用本地语言实现的。

def rev_manual_pos_gen(mylist):
    max_index = len(mylist) - 1
    return [ mylist[max_index - index] for index in range(len(mylist)) ]

def rev_manual_neg_gen(mylist):
    ## index is 0 to 9, but we need -1 to -10
    return [ mylist[-index-1] for index in range(len(mylist)) ]

def rev_manual_index_loop(mylist):
    a = []
    reverse_index = len(mylist) - 1
    for index in range(len(mylist)):
        a.append(mylist[reverse_index - index])
    return a
    
def rev_manual_loop(mylist):
    a = []
    reverse_index = len(mylist)
    for index, _ in enumerate(mylist):
        reverse_index -= 1
        a.append(mylist[reverse_index])
    return a
Run Code Online (Sandbox Code Playgroud)

对每种方法进行计时

以下是脚本的其余部分,用于为每种反转方法计时。它显示原地反转obj.reverse()和创建reversed(obj)迭代器总是最快的,而使用切片是创建副本的最快方法。

事实证明,除非必须,否则不要尝试自己创建一种方法!

loops_to_test = 100000
number_of_items = 10
list_to_reverse = list(range(number_of_items))
if number_of_items < 15:
    print("a: {}".format(list_to_reverse))
print('Loops: {:,}'.format(loops_to_test))
# List of the functions we want to test with the timer, in print order
fcns = [rev_in_place, reversed_iterator, rev_slice, rev_copy_reverse,
        reversed_with_list, rev_manual_pos_gen, rev_manual_neg_gen,
        rev_manual_index_loop, rev_manual_loop]
max_name_string = max([ len(fcn.__name__) for fcn in fcns ])
for fcn in fcns:
    a = copy(list_to_reverse) # copy to start fresh each loop
    out_str = ' | out = {}'.format(fcn(a)) if number_of_items < 15 else ''
    # Time in ms for the given # of loops on this fcn
    time_str = time_str_ms(timeit(lambda: fcn(a), number=loops_to_test))
    # Get the output string for this function
    fcn_str = '{}(a):'.format(fcn.__name__)
    # Add the correct string length to accommodate the maximum fcn name
    format_str = '{{fx:{}s}} {{time}}{{rev}}'.format(max_name_string + 4)
    print(format_str.format(fx=fcn_str, time=time_str, rev=out_str))
Run Code Online (Sandbox Code Playgroud)

计时结果

结果表明,缩放最适合最适合给定任务的内置方法。换句话说,随着对象元素数量的增加,内置方法开始具有更优越的性能结果。

您最好使用最好的内置方法,直接实现您的需要,而不是将事情串在一起。即如果您需要反向列表的副本,切片是最好的 - 它比从reversed()函数创建列表更快,并且比制作列表副本然后执行就地操作更快obj.reverse()。但是,如果这两种方法中的任何一种都是您真正需要的,那么它们会更快,但速度不会超过两倍。同时 - 自定义的手动方法可能需要更长的数量级,特别是对于非常大的列表。

对于缩放,对于 1000 项列表,reversed(<list>)函数调用需要约 30 毫秒来设置迭代器,原地反转只需要约 55 毫秒,使用切片方法需要约 210 毫秒来创建完整反转列表的副本,但是我制作的最快的手动方法花了 ~8400 毫秒!!

列表中有 2 个项目:

a: [0, 1]
Loops: 100,000
rev_in_place(a):             24.70 ms | out = [1, 0]
reversed_iterator(a):        30.48 ms | out = <list_reverseiterator object at 0x0000020242580408>
rev_slice(a):                31.65 ms | out = [1, 0]
rev_copy_reverse(a):         63.42 ms | out = [1, 0]
reversed_with_list(a):       48.65 ms | out = [1, 0]
rev_manual_pos_gen(a):       98.94 ms | out = [1, 0]
rev_manual_neg_gen(a):       88.11 ms | out = [1, 0]
rev_manual_index_loop(a):    87.23 ms | out = [1, 0]
rev_manual_loop(a):          79.24 ms | out = [1, 0]
Run Code Online (Sandbox Code Playgroud)

列表中有 10 个项目:

rev_in_place(a):             23.39 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_iterator(a):        30.23 ms | out = <list_reverseiterator object at 0x00000290A3CB0388>
rev_slice(a):                36.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_copy_reverse(a):         64.67 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
reversed_with_list(a):       50.77 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_pos_gen(a):      162.83 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_neg_gen(a):      167.43 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_index_loop(a):   152.04 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
rev_manual_loop(a):         183.01 ms | out = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
Run Code Online (Sandbox Code Playgroud)

并且列表中有 1000 个项目:

rev_in_place(a):             56.37 ms
reversed_iterator(a):        30.47 ms
rev_slice(a):               211.42 ms
rev_copy_reverse(a):        295.74 ms
reversed_with_list(a):      418.45 ms
rev_manual_pos_gen(a):     8410.01 ms
rev_manual_neg_gen(a):    11054.84 ms
rev_manual_index_loop(a): 10543.11 ms
rev_manual_loop(a):       15472.66 ms
Run Code Online (Sandbox Code Playgroud)


Paw*_*mar 25

对于倒转相同的列表,请使用:

array.reverse()
Run Code Online (Sandbox Code Playgroud)

要将反向列表分配到其他列表中,请使用:

newArray = array[::-1] 
Run Code Online (Sandbox Code Playgroud)


Sim*_*onM 24

使用切片,例如array = array [:: - 1],是一个巧妙的技巧,非常Pythonic,但对于新手可能有点模糊.使用reverse()方法是日常编码的好方法,因为它易于阅读.

但是,如果您需要像面试问题那样撤销列表,您可能无法使用这些内置方法.面试官将研究如何处理问题而不是Python知识的深度,需要一种算法方法.以下示例使用经典交换,可能是一种方法: -

def reverse_in_place(lst):      # Declare a function
    size = len(lst)             # Get the length of the sequence
    hiindex = size - 1
    its = size/2                # Number of iterations required
    for i in xrange(0, its):    # i is the low index pointer
        temp = lst[hiindex]     # Perform a classic swap
        lst[hiindex] = lst[i]
        lst[i] = temp
        hiindex -= 1            # Decrement the high index pointer
    print "Done!"

# Now test it!!
array = [2, 5, 8, 9, 12, 19, 25, 27, 32, 60, 65, 1, 7, 24, 124, 654]

print array                    # Print the original sequence
reverse_in_place(array)        # Call the function passing the list
print array                    # Print reversed list


**The result:**
[2, 5, 8, 9, 12, 19, 25, 27, 32, 60, 65, 1, 7, 24, 124, 654]
Done!
[654, 124, 24, 7, 1, 65, 60, 32, 27, 25, 19, 12, 9, 8, 5, 2]
Run Code Online (Sandbox Code Playgroud)

请注意,这不适用于元组或字符串序列,因为字符串和元组是不可变的,即,您无法写入它们来更改元素.

  • 经典交换可以通过`lst [hiindex],lst [i] = lst [i],lst [hiindex]`,我认为... ;-) (9认同)
  • @k4ppa:“array[::-1]”是完全可读且完全明确的*如果您了解Python*。“可读”并不意味着“以前从未使用过Python切片的人一定能够读懂它”;`[::-1]` 反转切片是 Python 中非常常见的习惯用法(您会在现有代码中一直遇到它),并且*如果您经常使用 Python*,它是完全可读的。当然,“first10 = []”、“for i in range(10):first10.append(array[i])”是清晰明确的,但这并不比“first10 = array[:10]”更好`。 (2认同)

Chr*_*nds 18

我发现(与其他一些建议相反)l.reverse()是迄今为止在Python 3和2中反转长列表的最快方法.我很想知道其他人是否可以复制这些时间.

l[::-1]可能更慢,因为它在反转之前复制列表.list()在迭代器周围添加调用reversed(l)必须添加一些开销.当然,如果你想要一个列表或迭代器的副本,那么使用那些相应的方法,但如果你只想反转列表,那么l.reverse()似乎是最快的方法.

功能

def rev_list1(l):
    return l[::-1]

def rev_list2(l):
    return list(reversed(l))

def rev_list3(l):
    l.reverse()
    return l
Run Code Online (Sandbox Code Playgroud)

名单

l = list(range(1000000))
Run Code Online (Sandbox Code Playgroud)

Python 3.5时序

timeit(lambda: rev_list1(l), number=1000)
# 6.48
timeit(lambda: rev_list2(l), number=1000)
# 7.13
timeit(lambda: rev_list3(l), number=1000)
# 0.44
Run Code Online (Sandbox Code Playgroud)

Python 2.7时序

timeit(lambda: rev_list1(l), number=1000)
# 6.76
timeit(lambda: rev_list2(l), number=1000)
# 9.18
timeit(lambda: rev_list3(l), number=1000)
# 0.46
Run Code Online (Sandbox Code Playgroud)

  • `list.reverse`是最快的,因为它反转到位 (3认同)

Swi*_*iss 17

for x in array[::-1]:
    do stuff
Run Code Online (Sandbox Code Playgroud)


Eya*_*vin 16

reversedlist:

>>> list1 = [1,2,3]
>>> reversed_list = list(reversed(list1))
>>> reversed_list
>>> [3, 2, 1]
Run Code Online (Sandbox Code Playgroud)


nop*_*ole 10

array=[0,10,20,40]
for e in reversed(array):
  print e
Run Code Online (Sandbox Code Playgroud)


小智 7

使用反转(数组)可能是最佳路线.

>>> array = [1,2,3,4]
>>> for item in reversed(array):
>>>     print item
Run Code Online (Sandbox Code Playgroud)

您是否需要了解如何在不使用内置的情况下实现此目的reversed.

def reverse(a):
    midpoint = len(a)/2
    for item in a[:midpoint]:
        otherside = (len(a) - a.index(item)) - 1
        temp = a[otherside]
        a[otherside] = a[a.index(item)]
        a[a.index(item)] = temp
    return a
Run Code Online (Sandbox Code Playgroud)

这应该花费O(N)时间.


H6.*_*H6. 6

另一种解决方案是使用numpy.flip

import numpy as np
array = [0, 10, 20, 40]
list(np.flip(array))
[40, 20, 10, 0]
Run Code Online (Sandbox Code Playgroud)


Tem*_*mak 5

如果要将反转列表的元素存储在其他变量中,则可以使用revArray = array[::-1]revArray = list(reversed(array)).

但第一个变种略快一些:

z = range(1000000)
startTimeTic = time.time()
y = z[::-1]
print("Time: %s s" % (time.time() - startTimeTic))

f = range(1000000)
startTimeTic = time.time()
g = list(reversed(f))
print("Time: %s s" % (time.time() - startTimeTic))
Run Code Online (Sandbox Code Playgroud)

输出:

Time: 0.00489711761475 s
Time: 0.00609302520752 s
Run Code Online (Sandbox Code Playgroud)

  • 下次,您可能想要使用`timeit`. (2认同)

Mar*_*des 5

组织值:

在Python中,列表的顺序也可以通过sort操作,以数字/字母顺序组织变量:

暂时:

print(sorted(my_list))
Run Code Online (Sandbox Code Playgroud)

常驻:

my_list.sort(), print(my_list)
Run Code Online (Sandbox Code Playgroud)

您可以使用标志“ reverse = True”进行排序:

print(sorted(my_list, reverse=True))

要么

my_list.sort(reverse=True), print(my_list)

没有组织

也许您不想对值进行排序,而只对值进行反转。然后我们可以这样做:

print(list(reversed(my_list)))

** 数字按列表顺序优先于字母。Python价值观的组织很棒。