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

array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)


我需要具有数组的元素,但要从头到尾。

#1 楼

您可以通过以下方式使用reversed函数:

>>> array=[0,10,20,40]
>>> for i in reversed(array):
...     print(i)


请注意,reversed(...)不返回列表。您可以使用list(reversed(array))获得反向列表。

评论


您不能只使用:array [::-1]吗?

–kdlannoy
16年4月24日在9:58

@kdlannoy根据答案中链接到的页面,“与扩展切片相比,例如range(1,4)[::-1],reversed()更易于阅读,运行更快并且使用的内存明显更少。 ”

– Jim Oldfield
16年8月20日在15:55

当我测试时,切片速度大约是原来的两倍(当反转10k元素列表并从中创建列表时)。我没有测试内存消耗。但是,如果您以后不需要转换为列表,则反向操作可能会更快。

–达卡龙
16年8月23日在14:01

值得注意的是,这与reverse([1,2,3]),n.b不同。最后的“ d” ...是下面的其他答案之一,它就地执行此操作,而此操作返回一个迭代器。

–卢西亚诺
16-10-8在9:36

为什么要使用reversed()而不是切片?阅读Python Zen,规则7:可读性至关重要!

– kramer65
17年4月25日在8:26

#2 楼

>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]


扩展的切片语法在Python中得到了很好的解释。2.3.5的新发行版

如有特殊要求,请提供注释,这是最新的切片文档。

评论


它适用于任何可交互的对象,而不仅仅是列表。缺点是它不到位。

–瑞士
2010-10-15在7:04



@Tim它返回一个切片,因此不会更改实际的列表内容

– fortran
2010-10-15在7:04



@lunixbochs反转会返回迭代器,而不是Python 3中的列表。

–瑞士
2010-10-15在7:09



除非自然正确地封装在数组中

–埃纳尔·彼得森(Einar Petersen)
2010-11-29在11:54

我同意@Swiss。因为问题是+1,所以我需要从最后到最后都有一个数组的元素。 -反向返回listreverseiterator对象(Python 2.7.x),然后必须对其进行迭代-反向切片将返回反向列表/元组/字符串(取决于要切片的内容)。 @Einar Petersen正在反转字符串,因此输出正确。试试:co2 = ['ae','ad','ac','ab','aa','z','y','x','w','v','u',' t','s','r','q','p','o','n','m','l','k','j','i','h' ,'g','f','e','d','c','b','a'] >>> co2 [::-1]

–亚伦·牛顿
2012年8月12日在3:25



#3 楼

>>> L = [0,10,20,40]
>>> L.reverse()
>>> L
[40, 20, 10, 0]




>>> L[::-1]
[40, 20, 10, 0]


评论


[start:stop:step]所以step为-1

– papalagi
2012年9月26日下午3:36

详细信息:第一个在原位修改列表,第二个仅返回新的反向列表,但不修改原始列表。

–franzlorenzon
13-10-29在14:02



第二个示例应该是L = L [::-1]以实际上反转列表,否则您只返回相反的值

–robertmoggach
2014年9月30日,下午1:53

假设我有l = [1,2,3,4,5,6]且n = 2他们的结果必须是[6,5,1,2,3,4],我们该怎么做

– Atul Jain
15年1月24日在6:56

您可以这样做:b = l [-n:] b.reverse()l = b + l [:len(l)-n]

–Shoaib Shakeel
2015年12月10日9:41



#4 楼

使用切片,例如array = array [::-1]是一个巧妙的技巧,非常具有Python风格,但对于新手来说可能有些晦涩。使用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]


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

评论


经典交换可以通过lst [hiindex],lst [i] = lst [i],lst [hiindex]完成,我认为... ;-)

–萨莫斯(Samoth)
17 Mar 25 '17 at 10:50

@Samoth语法不太清楚,行为也不十分明显。不同的步骤更有意义。

–安东尼
18年7月7日在18:29

为什么人们说诸如array [::-1]之类的东西是pythonic? python zen告诉我们,显式比隐式和可读性要好。这样的东西根本不是明确的和可读的。

– k4ppa
18年8月20日在15:36

如果您了解Python,@ k4ppa:array [::-1]完全可读,也非常明确。 “可读”并不意味着“以前从未使用过Python切片的人必须能够阅读它”; [::-1]反转片是Python中一个非常荒谬的惯用语(您会一直在现有代码中遇到它),如果您经常使用Python,它是完全可读的。当然,对于range(10)中的i来说,first10 = []:first10.append(array [i])是清晰明确的,但这并不比first10 = array [:10]好。

–ShadowRanger
1月7日18:00



为什么迭代次数为2?它背后的逻辑是什么?另外,如果长度不是偶数怎么办。那会是ceil(size / 2)

–匿名者
10月30日15:39

#5 楼

要反转相同的列表,请使用:

array.reverse()


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

newArray = array[::-1] 


#6 楼

我发现(与其他建议相反)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


列表

l = list(range(1000000))


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



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


评论


list.reverse是最快的,因为它在原地反转

– warvariuc
17年9月17日在18:38

您是正确的list.reverse()最快,但是您要对反向进行惩罚(当您不想创建新列表时,最好以反向顺序迭代现有列表而不更改原始列表,这是最佳选择),并且切片(这也避免了原始列表的变异,并且通常比输入较小时要快)。是的,如果您不需要副本,那么复制的任何内容都会更昂贵,但是很多时候,您都不想更改原始值。

–ShadowRanger
1月7日18:11



看起来reverse仍然会丢失到list.reverse(),但是考虑到它不会突变输入列表,因此在许多情况下它会更好。反向的损失很小(比list.reverse()长约1/6)。

–ShadowRanger
1月7日18:17



#7 楼

for x in array[::-1]:
    do stuff


评论


这种切片方法不是很可读。 Python方式是使用reverse()方法。 ;-)

– SimonM
18年5月31日在12:21

@SimonM reverse()绝对一目了然。

–瑞士
18年6月1日在22:22

#8 楼

带有解释和计时结果的方法摘要
有三种不同的内置方法可以反转列表。哪种方法最好取决于您是否需要:

就地反转现有列表(更改原始列表变量)
object.reverse()方法


创建一个反向列表的迭代器(因为您要将其馈入for循环,生成器等)。

最佳解决方案是reversed(object),它可以创建反向列表iterator


以相反的顺序创建列表的副本(以保留原始列表)
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)
 

方法1:反向如果目标只是为了反转现有列表中项目的顺序,而不要遍历它们或使副本可用,请使用<list>.reverse()函数。直接在列表对象上运行此命令,所有项目的顺序将颠倒:
请注意,以下内容将反转给定的原始变量,即使它也返回已反转的列表。也就是说,您可以使用此函数输出创建副本。通常,您不会为此创建函数,但是计时脚本需要它。
我们测试这两种方式的性能-首先只是就地反转列表(更改原始列表),然后复制列表,然后对其进行反转,以查看与其他方法相比,这是否是创建反转副本的最快方法。
 def rev_in_place(mylist):
    mylist.reverse()
    return mylist

def rev_copy_reverse(mylist):
    a = copy(mylist)
    a.reverse()
    return a
 

方法2:使用切片反向列表obj[::-1]内置索引切片方法使您可以复制任何索引对象的一部分。

不影响原始对象
它将构建完整列表,而不是迭代器

。通用语法为:<object>[first_index:last_index:step]。要利用切片来创建简单的反向列表,请使用:<list>[::-1]。将选项保留为空时,它将其设置为对象的第一个和最后一个元素的默认值(如果步长为负,则为默认值)。
索引允许人们使用负数,该负数从对象的末尾开始计数向后索引(即-2是倒数第二个项目)。当步长为负数时,它将以最后一项开始,并以该数量向后索引。
 def rev_slice(mylist):
    a = mylist[::-1]
    return a
 

方法3:使用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
 

方法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
 

为每种方法设定时间
以下是脚本的其余部分,为每种反向方法计时。它显示了使用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))
 

计时结果
结果显示缩放比例最好与内置方法配合使用适合于给定的任务。换句话说,随着对象元素数量的增加,内置方法开始表现出更好的性能结果。
使用最好的内置方法直接实现所需的效果比将事物串起来还更好一起。即切片是最好的,如果您需要反向列表的副本-它比从reversed()函数创建列表快,并且比复制列表然后就地执行obj.reverse()快。但是,如果您真的需要这些方法中的任何一种,它们就会更快,但速度永远不会超过两倍。同时-自定义,手动方法可能要花几个数量级,特别是对于非常大的列表。
为了进行缩放,列表项为1000,reversed(<list>)函数调用大约需要30毫秒来设置迭代器,原位反向仅需要55毫秒,使用slice方法需要大约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]
 

列表中有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]
 

列表中有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
 


#9 楼

使用reversedlist时:

>>> list1 = [1,2,3]
>>> reversed_list = list(reversed(list1))
>>> reversed_list
>>> [3, 2, 1]


#10 楼

array=[0,10,20,40]
for e in reversed(array):
  print e


#11 楼

使用reversed(array)可能是最佳途径。

>>> array = [1,2,3,4]
>>> for item in reversed(array):
>>>     print item


您是否需要了解如何在不使用内置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


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

评论


正在寻找不使用反向功能的方法。谢谢。

– Bernard'Beta Berlin'Parah
16年6月18日在20:50

或使用list = list.reverse()进行原位反转

– SimonM
18年5月31日在12:23

#12 楼

如果要将反向列表的元素存储在其他变量中,则可以使用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))


输出:

Time: 0.00489711761475 s
Time: 0.00609302520752 s


评论


下次,您可能要使用timeit。

– Grooveplex
16年7月28日在8:28

#13 楼

使用一些逻辑

使用一些古老的逻辑来练习面试。


从前向后交换数字。使用两个指针index[0] and index[last]


def reverse(array):
    n = array
    first = 0
    last = len(array) - 1
    while first < last:
      holder = n[first]
      n[first] = n[last]
      n[last] = holder
      first += 1
      last -= 1
    return n

input -> [-1 ,1, 2, 3, 4, 5, 6]
output -> [6, 1, 2, 3, 4, 5, -1]


评论


如果我们将列表一分为二,然后将第一个与最后一个索引交换,则时间复杂度将比列出的示例更有效。

–以色列曼佐
19年1月2日,下午2:17

#14 楼

使用列表理解:

[array[n] for n in range(len(array)-1, -1, -1)]


#15 楼

使用最少的内置功能(假设它是采访设置)

array = [1, 2, 3, 4, 5, 6,7, 8]
inverse = [] #create container for inverse array
length = len(array)  #to iterate later, returns 8 
counter = length - 1  #because the 8th element is on position 7 (as python starts from 0)

for i in range(length): 
   inverse.append(array[counter])
   counter -= 1
print(inverse)


#16 楼

另一个解决方案是对此使用numpy.flip

import numpy as np
array = [0, 10, 20, 40]
list(np.flip(array))
[40, 20, 10, 0]


#17 楼

您还可以使用数组索引的按位补码来反向遍历数组:
>>> array = [0, 10, 20, 40]
>>> [array[~i] for i, _ in enumerate(array)]
[40, 20, 10, 0]

无论做什么,都不要这样做;)

#18 楼

严格来说,问题不是如何反向返回列表,而是如何反向显示示例列表名称为array的列表。

要反向转换名为"array"的列表,请使用array.reverse()

通过使用array = array[::-1]将列表定义为自身的切片修改,还可以使用上述非常有用的slice方法来将列表反向显示。

评论


最后一句话不正确,这不会在适当的位置反转列表。应该说array [:] = array [::-1]

–安蒂·哈帕拉(Antti Haapala)
15年2月16日在16:17

#19 楼

有3种方法来获取反向列表:


切片方法1:reversed_array = array[-1::-1] reversed_array2 = array[::-1]
使用内置函数:reversed_array = array.reverse()

第三个函数实际上将列表对象反转到位。这意味着不保留原始数据的副本。如果您不想维护旧版本,这是一个好方法。但是,如果您确实想要原始版本和反向版本,这似乎不是解决方案。

#20 楼

您的需求到Python中最直接的翻译是以下for语句:

for i in xrange(len(array) - 1, -1, -1):
   print i, array[i]


这很神秘,但可能有用。

#21 楼

def reverse(my_list):
  L = len(my_list)
  for i in range(L/2):
    my_list[i], my_list[L-i - 1] = my_list[L-i-1], my_list[i]
  return my_list


评论


//楼层除法运算符会更好。

– Valentin Podkamennyi
19年5月20日在7:45

#22 楼

def reverse(text):
    output = []
    for i in range(len(text)-1, -1, -1):
        output.append(text[i])
    return output


#23 楼

您总是可以像对待堆栈一样对待列表,只是从列表的后端将元素从堆栈顶部弹出。这样,您就可以利用堆栈的先进先出特性。当然,您正在使用第一个数组。我喜欢这种方法,因为它非常直观,您可以看到一个列表是从后端使用的,而另一个列表是从前端构建的。

>>> l = [1,2,3,4,5,6]; nl=[]
>>> while l:
        nl.append(l.pop())  
>>> print nl
[6, 5, 4, 3, 2, 1]


#24 楼

list_data = [1,2,3,4,5]
l = len(list_data)
i=l+1
rev_data = []
while l>0:
  j=i-l
  l-=1
  rev_data.append(list_data[-j])
print "After Rev:- %s" %rev_data 


#25 楼

使用

print(reversed(list_name))


评论


<位于0x0000021C517D3DA0的list_reverseiterator对象>

–Jean-FrançoisFabre♦
11月19日下午13:45

此输出不可读...使用print(list(reversed(list_name)))代替。

–最大
12月21日16:10

#26 楼

>>> l = [1, 2, 3, 4, 5]
>>> print(reduce(lambda acc, x: [x] + acc, l, []))
[5, 4, 3, 2, 1]


评论


该解决方案比l [::-1]慢约4.5k倍,同时清晰得多。不幸的是,Python中的函数式编程相当慢。

–达卡龙
16年8月23日在13:58

#27 楼

通过切换相反索引的参考原位反转:

>>> l = [1,2,3,4,5,6,7]    
>>> for i in range(len(l)//2):
...     l[i], l[-1-i] = l[-1-i], l[i]
...
>>> l
[7, 6, 5, 4, 3, 2, 1]


评论


适用于奇数长度列表!

–user4776653
16-10-25在2:01

我的解决方案是对的!您知道python如何实现索引编制。从右到左,您有0,1,2 ...,从左到右,您有-1,-2,-3 ..等。要反转列表,请将其切成两部分,然后将索引乘以右侧则由左侧的对立减一。

–user4776653
16-10-25在18:49

#28 楼

可以使用__reverse__来完成,它会返回一个生成器。

>>> l = [1,2,3,4,5]
>>> for i in l.__reversed__():
...   print i
... 
5
4
3
2
1
>>>


#29 楼

用一个行代码反转用户输入值:

for i in input()[::-1]: print(i,end='')


#30 楼

此类使用Python魔术方法和迭代器进行反转,并反转列表:

class Reverse(object):
    """ Builds a reverse method using magic methods """

    def __init__(self, data):
        self.data = data
        self.index = len(data)


    def __iter__(self):
        return self

    def __next__(self):
        if self.index == 0:
            raise StopIteration

        self.index = self.index - 1
        return self.data[self.index]


REV_INSTANCE = Reverse([0, 10, 20, 40])

iter(REV_INSTANCE)

rev_list = []
for i in REV_INSTANCE:
    rev_list.append(i)

print(rev_list)  


输出

[40, 20, 10, 0]