如何反转列表或向后循环?

如何在Python中反向迭代列表?


另请参阅:我如何获得列表的反向副本(在链接方法后避免单独的语句)?

1860797 次浏览
>>> xs = [0, 10, 20, 40]>>> xs[::-1][40, 20, 10, 0]

扩展切片语法解释为这里。另请参阅留档

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

要获得新的反向列表,请应用#0函数并将项目收集到#1中:

>>> xs = [0, 10, 20, 40]>>> list(reversed(xs))[40, 20, 10, 0]

向后遍历列表:

>>> xs = [0, 10, 20, 40]>>> for x in reversed(xs):...     print(x)4020100

使用#0反转列表就地

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

使用切片以相反的顺序创建新的列表:

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

将您的需求最直接地翻译成Python是这样的for语句:

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

这是相当神秘的,但可能是有用的。

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

array.reverse()

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

newArray = array[::-1]

问题不是如何反向返回一个列表,而是如何用示例列表名称array反向返回一个列表。

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

所描述的非常有用的切片方法也可用于通过使用array[:] = array[::-1]将列表定义为自身的切片修改来反转列表。

使用列表理解:

[array[n] for n in range(len(array)-1, -1, -1)]
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

如果您想将反向列表的元素存储在其他变量中,那么您可以使用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 sTime: 0.00609302520752 s
>>> L = [1, 2, 3, 4]>>> L = [L[-i] for i in range(1, len(L) + 1)]>>> L[4, 3, 2, 1]
def reverse(text):output = []for i in range(len(text)-1, -1, -1):output.append(text[i])return output

使用反向(数组)可能是最好的路线。

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

如果您需要了解如何在不使用内置reversed的情况下实现这一点。

def reverse(a):midpoint = len(a)/2for item in a[:midpoint]:otherside = (len(a) - a.index(item)) - 1temp = a[otherside]a[otherside] = a[a.index(item)]a[a.index(item)] = tempreturn a

这需要O(N)时间。

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

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

使用切片,例如数组=数组[::-1],是一个巧妙的技巧,非常Pythonic,但对于新手来说可能有点晦涩。使用反向()方法是日常编码的好方法,因为它易于阅读。

但是,如果你需要像面试问题中那样颠倒一个列表,你可能无法使用像这样的内置方法。面试官将关注你如何处理问题,而不是Python知识的深度,需要一种算法方法。以下示例,使用经典的交换,可能是一种方法:-

def reverse_in_place(lst):      # Declare a functionsize = len(lst)             # Get the length of the sequencehiindex = size - 1its = size/2                # Number of iterations requiredfor i in xrange(0, its):    # i is the low index pointertemp = lst[hiindex]     # Perform a classic swaplst[hiindex] = lst[i]lst[i] = temphiindex -= 1            # Decrement the high index pointerprint "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 sequencereverse_in_place(array)        # Call the function passing the listprint 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]

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

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

通过切换相反索引的引用来就地反转:

>>> 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]

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

l[::-1]可能更慢,因为它在反转列表之前复制列表。在reversed(l)所做的迭代器周围添加list()调用必须增加一些开销。当然,如果你想要列表或迭代器的副本,那么使用这些相应的方法,但如果你只想反转列表,那么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.48timeit(lambda: rev_list2(l), number=1000)# 7.13timeit(lambda: rev_list3(l), number=1000)# 0.44

Python 2.7计时

timeit(lambda: rev_list1(l), number=1000)# 6.76timeit(lambda: rev_list2(l), number=1000)# 9.18timeit(lambda: rev_list3(l), number=1000)# 0.46

您还可以使用数组索引的按位补码反向遍历数组:

>>> array = [0, 10, 20, 40]>>> [array[~i] for i, _ in enumerate(array)][40, 20, 10, 0]

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

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

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

#0#1

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

用一些逻辑

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

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

def reverse(array):n = arrayfirst = 0last = len(array) - 1while first < last:holder = n[first]n[first] = n[last]n[last] = holderfirst += 1last -= 1return n
input -> [-1 ,1, 2, 3, 4, 5, 6]output -> [6, 5, 4, 3, 2, 1, -1]

使用最少的内置函数,假设它是面试设置

array = [1, 2, 3, 4, 5, 6,7, 8]inverse = [] #create container for inverse arraylength = len(array)  #to iterate later, returns 8counter = 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 -= 1print(inverse)

使用

print(list(reversed(list_name)))

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

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

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

class Reverse(object):""" Builds a reverse method using magic methods """
def __init__(self, data):self.data = dataself.index = len(data)

def __iter__(self):return self
def __next__(self):if self.index == 0:raise StopIteration
self.index = self.index - 1return 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]

下面是一种使用发生器懒惰地评估反向的方法:

def reverse(seq):for x in range(len(seq), -1, -1): #Iterate through a sequence starting from -1 and increasing by -1.yield seq[x] #Yield a value to the generator

现在像这样迭代:

for x in reverse([1, 2, 3]):print(x)

如果你需要一个列表:

l = list(reverse([1, 2, 3]))

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

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

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

  1. 切片方法1:reversed_array = array[-1::-1]

  2. 切片方法2:reversed_array2 = array[::-1]

  3. 使用内置函数:reversed_array = array.reverse()

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

逆向方法总结

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

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

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

测试脚本

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

from timeit import timeitfrom copy import copy
def time_str_ms(t):return '{0:8.2f} ms'.format(t * 1000)

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

方法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) - 1return [ 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 -10return [ mylist[-index-1] for index in range(len(mylist)) ]
def rev_manual_index_loop(mylist):a = []reverse_index = len(mylist) - 1for 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 -= 1a.append(mylist[reverse_index])return a

每种方法定时

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

这也证明了不要试图自己创造一种方法,除非你必须这样做!

loops_to_test = 100000number_of_items = 10list_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 orderfcns = [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 loopout_str = ' | out = {}'.format(fcn(a)) if number_of_items < 15 else ''# Time in ms for the given # of loops on this fcntime_str = time_str_ms(timeit(lambda: fcn(a), number=loops_to_test))# Get the output string for this functionfcn_str = '{}(a):'.format(fcn.__name__)# Add the correct string length to accommodate the maximum fcn nameformat_str = '\{\{fx:{}s}} \{\{time}}\{\{rev}}'.format(max_name_string + 4)print(format_str.format(fx=fcn_str, time=time_str, rev=out_str))

计时结果

结果表明,缩放最适用于最适合特定类型反转的内置方法。换句话说,随着对象元素数量的增加,内置方法比其他方法更胜一筹。

直接实现你需要的内置方法比将东西串在一起做得更好。即,如果你需要反向列表的副本,切片是最好的-它比从list(reversed(obj))函数创建重复列表更快,比复制列表然后就地执行obj.reverse()更快,但速度永远不会超过两倍。同时-自定义方法在大列表中需要的时间更长。

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

列表中有2个项目:

a: [0, 1]Loops: 100,000rev_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 msreversed_iterator(a):        30.47 msrev_slice(a):               211.42 msrev_copy_reverse(a):        295.74 msreversed_with_list(a):      418.45 msrev_manual_pos_gen(a):     8410.01 msrev_manual_neg_gen(a):    11054.84 msrev_manual_index_loop(a): 10543.11 msrev_manual_loop(a):       15472.66 ms

组织价值观

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

打印(排序(my_list))

常设:

my_list.sort(), print(my_list)

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

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

没有组织

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

print(list(reversed(my_list)))

**在列表顺序中,数字优先于字母。Python值的组织很棒。

编辑1:一个错误的版主声称我的答案是副本,并删除了我的旧帖子。

我在一次工作面试的python代码测试中遇到了这个问题。下面是我的答案。注意它适用于任何长度的任何值

def get_reverse(list_check, count_num):final_list =[]for index in range(list_length):value = list_check[count_num]final_list.append(value)count_num = count_num -1
return final_list
new_list = ['A', 'GOAT', 'C', 'D', 'Mac']
list_length = len(new_list)x = list_length -1
print(get_reverse(new_list, x))

一个干净简单的类对象来解决您的问题。

class lister():def reverse(self):return  [self[len(self)-e]for e,x in enumerate(self,start=1)]print(lister.reverse([0, 10, 20, 40]))

使用列表理解和abs的替代方法

array = [0, 10, 20, 40]
reversed_array = [array[abs(indx)] for indx in range(abs(len(array)-1),1)]            
reversed_array[40, 20, 10, 0]
The cute Solution

class List_reverse():def reverse_list(self):list = [1, 2, 3, 4, 5, 6]list1 = []for i in range(1, len(list)+1):list1.append(list[-i])print(list1)

if __name__ == "__main__":obj = List_reverse()obj.reverse_list()enter code here