【发布时间】:2011-04-25 19:17:41
【问题描述】:
如何在 Python 中执行以下操作?
array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)
我需要一个数组的元素,但是从头到尾。
【问题讨论】:
-
或者更确切地说“我如何反转预先排序的列表?” (鉴于这个使大多数答案脱轨的特殊测试用例,这是一个正确的问题:)
如何在 Python 中执行以下操作?
array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)
我需要一个数组的元素,但是从头到尾。
【问题讨论】:
>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]
扩展切片语法在 Python What's new Entry for release 2.3.5中有很好的解释
通过评论中的特殊要求this is the most current slice documentation。
【讨论】:
reversed 返回一个 listreverseiterator 对象(Python 2.7.x),然后必须被迭代 - 反向切片返回一个反向列表/元组/str(取决于你切片的内容)。 @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]
for x in array[::-1]:
do stuff
【讨论】:
您可以为此使用reversed 函数:
>>> array=[0,10,20,40]
>>> for i in reversed(array):
... print(i)
请注意,reversed(...) 不会返回列表。您可以使用list(reversed(array)) 获取反向列表。
【讨论】:
reverse 可能会更快,如果您之后不需要强制转换到列表。
reversed()而不是切片?阅读 Python 之禅,第 7 条规则:可读性很重要!
>>> L = [0,10,20,40]
>>> L.reverse()
>>> L
[40, 20, 10, 0]
或者
>>> L[::-1]
[40, 20, 10, 0]
【讨论】:
L=L[::-1] 以实际反转列表,否则您只会反向返回值
b = l[-n:] b.reverse() l = b + l[:len(l) - n]
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[:] = 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 s
Time: 0.00609302520752 s
【讨论】:
timeit。
>>> 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
【讨论】:
使用 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) 时间。
【讨论】:
您总是可以将列表视为堆栈,只需从列表后端弹出堆栈顶部的元素。这样,您就可以利用堆栈的先进后出特性。当然,您正在使用第一个数组。我确实喜欢这种方法,因为它非常直观,您可以看到一个列表是从后端使用的,而另一个列表是从前端构建的。
>>> l = [1,2,3,4,5,6]; nl=[]
>>> while l:
nl.append(l.pop())
>>> print nl
[6, 5, 4, 3, 2, 1]
【讨论】:
使用切片,例如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]
请注意,这不适用于元组或字符串序列,因为字符串和元组是不可变的,也就是说,您不能写入它们来更改元素。
【讨论】:
lst[hiindex], lst[i] = lst[i], lst[hiindex] 完成,我认为... ;-)
array[::-1] 非常易读且非常明确如果您了解 Python。 “可读”并不意味着“以前从未使用过 Python 切片的人必须能够阅读它”; [::-1] 反转切片在 Python 中是一个非常常见的习语(你会一直在现有代码中遇到它),如果你经常使用 Python,它是完全可读的。当然,first10 = []、for i in range(10): first10.append(array[i]) 清晰明确,但这并不比first10 = array[:10] 更好。
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
【讨论】:
>>> l = [1, 2, 3, 4, 5]
>>> print(reduce(lambda acc, x: [x] + acc, l, []))
[5, 4, 3, 2, 1]
【讨论】:
l[::-1] 慢了大约 4.5k 倍,同时更不清晰。遗憾的是,Python 中的函数式编程相当缓慢。
通过切换相反索引的引用来就地反转:
>>> 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.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 是最快的,因为它原地反转
list.reverse() 是最快的,但你在惩罚 reversed(最好在你不想要一个新的list 时使用,只是以相反的顺序迭代现有的list而不改变原始的)和切片(这也避免了改变原始的list,并且当输入很小时通常比reversed更快)。是的,如果您不需要副本,那么复制的任何东西都会更昂贵,但很多时候,您不想改变原始值。
reversed still loses to list.reverse() 即便如此,但鉴于它不会改变输入list,在许多情况下它会更好。 reversed 的损失很小(比 list.reverse() 长约 1/6)。
也可以使用数组索引的bitwise complement逆向遍历数组:
>>> 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
...
5
4
3
2
1
>>>
【讨论】:
使用一些老派的逻辑来练习面试。
前后交换数字。使用两个指针
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]
【讨论】:
使用最少的内置函数,假设是面试设置
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)
【讨论】:
使用
print(reversed(list_name))
【讨论】:
<list_reverseiterator object at 0x0000021C517D3DA0>
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 = 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]
【讨论】:
这是一种使用生成器懒惰地评估反向的方法:
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 np
array = [0, 10, 20, 40]
list(np.flip(array))
[40, 20, 10, 0]
【讨论】: