How can I do the following in Python?
array = [0, 10, 20, 40]
for (i = array.length() - 1; i >= 0; i--)
I need to have the elements of an array, but from the end to the beginning.
You can make use of the reversed
function for this as:
>>> array=[0,10,20,40]
>>> for i in reversed(array):
... print(i)
Note that reversed(...)
does not return a list. You can get a reversed list using list(reversed(array))
.
>>> L = [0,10,20,40]
>>> L[::-1]
[40, 20, 10, 0]
Extended slice syntax is explained well in the Python What's new Entry for release 2.3.5
By special request in a comment this is the most current slice documentation.
Using slicing, e.g. array = array[::-1], is a neat trick and very Pythonic, but a little obscure for newbies maybe. Using the reverse() method is a good way to go in day to day coding because it is easily readable.
However, if you need to reverse a list in place as in an interview question, you will likely not be able to use built in methods like these. The interviewer will be looking at how you approach the problem rather than the depth of Python knowledge, an algorithmic approach is required. The following example, using a classic swap, might be one way to do it:-
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]
Note that this will not work on Tuples or string sequences, because strings and tuples are immutable, i.e., you cannot write into them to change elements.
There are three different built-in ways to reverse a list. Which method is best depends on whether you need to:
object.reverse()
methodreversed(object)
which creates the iteratorobject[::-1]
From a speed perspective, it is best to use the built-in functions to reverse a list. In this case, they are 2 to 8 times faster on short lists (10 items), and up to ~300+ times faster on long lists compared to a manually-created loop or generator. This makes sense as they are written in a native language (i.e. C), have experts creating them, scrutiny, and optimization. They are also less prone to defects and more likely to handle edge and corner cases.
Put all the code snippets in this answer together to make a script that will run the different ways of reversing a list that are described below. It will time each method while running it 100,000 times. The results are shown in the last section for lists of length 2, 10, and 1000 items.
from timeit import timeit
from copy import copy
def time_str_ms(t):
return '{0:8.2f} ms'.format(t * 1000)
If the goal is just to reverse the order of the items in an existing list, without looping over them or getting a copy to work with, use the <list>.reverse()
function. Run this directly on a list object, and the order of all items will be reversed:
Note that the following will reverse the original variable that is given, even though it also returns the reversed list back. i.e. you can create a copy by using this function output. Typically, you wouldn't make a function for this, but the timing script requires it.
We test the performance of this two ways - first just reversing a list in-place (changes the original list), and then copying the list and reversing it afterward to see if that is the fastest way to create a reversed copy compared to the other methods.
def rev_in_place(mylist):
mylist.reverse()
return mylist
def rev_copy_reverse(mylist):
a = copy(mylist)
a.reverse()
return a
obj[::-1]
The built-in index slicing method allows you to make a copy of part of any indexed object.
The generic syntax is: <object>[first_index:last_index:step]
. To exploit slicing to create a simple reversed list, use: <list>[::-1]
. When leaving an option empty, it sets them to defaults of the first and last element of the object (reversed if the step size is negative).
Indexing allows one to use negative numbers, which count from the end of the object's index backwards (i.e. -2 is the second to last item). When the step size is negative, it will start with the last item and index backward by that amount.
def rev_slice(mylist):
a = mylist[::-1]
return a
reversed(obj)
iterator functionThere is a reversed(indexed_object)
function:
Test with both a raw iterator, and creating a list from the iterator.
def reversed_iterator(mylist):
a = reversed(mylist)
return a
def reversed_with_list(mylist):
a = list(reversed(mylist))
return a
As the timing shows, creating your own methods of indexing is a bad idea. Use the built-in methods unless you really do need to do something custom. This simply means learning the built-in methods.
That said, there is not a huge penalty with smaller list sizes, but when you scale up the penalty becomes tremendous. The code below could be optimized, I'm sure, but it can't ever match the built-in methods as they are directly implemented in a native language.
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
Following is the rest of the script to time each method of reversing. It shows reversing in place with obj.reverse()
and creating the reversed(obj)
iterator are always the fastest, while using slices is the fastest way to create a copy.
It also proves not to try to create a way of doing it on your own unless you have to!
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))
The results show that scaling works best with the built-in methods best suited for a given task. In other words, as the object element count increases, the built-in methods begin to have far superior performance results.
You are also better off using the best built-in method that directly achieves what you need than to string things together. i.e. slicing is best if you need a copy of the reversed list - it's faster than creating a list from the reversed()
function, and faster than making a copy of the list and then doing an in-place obj.reverse()
. But if either of those methods are really all you need, they are faster, but never by more than double the speed. Meanwhile - custom, manual methods can take orders of magnitude longer, especially with very large lists.
For scaling, with a 1000 item list, the reversed(<list>)
function call takes ~30 ms to setup the iterator, reversing in-place takes just ~55 ms, using the slice method takes ~210 ms to create a copy of the full reversed list, but the quickest manual method I made took ~8400 ms!!
With 2 items in the list:
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]
With 10 items in the list:
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]
And with 1000 items in the list:
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
I find (contrary to some other suggestions) that l.reverse()
is by far the fastest way to reverse a long list in Python 3 and 2. I'd be interested to know if others can replicate these timings.
l[::-1]
is probably slower because it copies the list prior to reversing it. Adding the list()
call around the iterator made by reversed(l)
must add some overhead. Of course if you want a copy of the list or an iterator then use those respective methods, but if you want to just reverse the list then l.reverse()
seems to be the fastest way.
Functions
def rev_list1(l):
return l[::-1]
def rev_list2(l):
return list(reversed(l))
def rev_list3(l):
l.reverse()
return l
List
l = list(range(1000000))
Python 3.5 timings
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 timings
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
Using reversed(array) would be the likely best route.
>>> array = [1,2,3,4]
>>> for item in reversed(array):
>>> print item
Should you need to understand how could implement this without using the built in 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
This should take O(N) time.
If you want to store the elements of reversed list in some other variable, then you can use revArray = array[::-1]
or revArray = list(reversed(array))
.
But the first variant is slightly faster:
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))
Output:
Time: 0.00489711761475 s
Time: 0.00609302520752 s
Another solution would be to use numpy.flip for this
import numpy as np
array = [0, 10, 20, 40]
list(np.flip(array))
[40, 20, 10, 0]
Using some old school logic to practice for interviews.
Swapping numbers front to back. Using two pointers
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]
You can also use the bitwise complement of the array index to step through the array in reverse:
>>> array = [0, 10, 20, 40]
>>> [array[~i] for i, _ in enumerate(array)]
[40, 20, 10, 0]
Whatever you do, don't do it this way ;)
With minimum amount of built-in functions, assuming it's interview settings
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)
Strictly speaking, the question is not how to return a list in reverse but rather how to reverse a list with an example list name array
.
To reverse a list named "array"
use array.reverse()
.
The incredibly useful slice method as described can also be used to reverse a list in place by defining the list as a sliced modification of itself using array = array[::-1]
.
ORGANIZING VALUES:
In Python, lists' order too can be manipulated with sort, organizing your variables in numerical/alphabetical order: Temporarily:
print(sorted(my_list))
Permanent:
my_list.sort(), print(my_list)
You can sort with the flag "reverse=True":
print(sorted(my_list, reverse=True))
or
my_list.sort(reverse=True), print(my_list)
WITHOUT ORGANIZING
Maybe you do not want to sort values, but only reverse the values. Then we can do it like this:
print(list(reversed(my_list)))
**Numbers have priority over alphabet in listing order. The Python values' organization is awesome.
Edit 1: a mistaken moderator claimed that my answer was a copy and deleted my old post.
You could always treat the list like a stack just popping the elements off the top of the stack from the back end of the list. That way you take advantage of first in last out characteristics of a stack. Of course you are consuming the 1st array. I do like this method in that it's pretty intuitive in that you see one list being consumed from the back end while the other is being built from the front end.
>>> l = [1,2,3,4,5,6]; nl=[]
>>> while l:
nl.append(l.pop())
>>> print nl
[6, 5, 4, 3, 2, 1]
There are 3 methods to get the reversed list:
Slicing Method 1: reversed_array = array[-1::-1]
Slicing Method 2:
reversed_array2 = array[::-1]
Using the builtin function: reversed_array = array.reverse()
The third function actually reversed the list object in place. That means no copy of pristine data is maintained. This is a good approach if you don't want to maintain the old version. But doesn't seem to be a solution if you do want the pristine and reversed version.