Reverse a list without using built-in functions

Question:

I’m using Python 3.5.

As part of a problem, I’m trying to design a function that takes a list as input and reverts it. So if x = [a, b, c] the function would make x = [c, b, a].

The problem is, I’m not allowed to use any built-in functions, and it has got me stuck. My initial thought was the following loop inside a function:

for revert in range(1, len(x) + 1):
    y.append(x[-revert])

And it works. But the problem is I’m using len(x), which I believe is a built-in function, correct?

So I searched around and have made the following very simple code:

y = x[::-1]

Which does exactly what I wanted, but it just seems almost too simple/easy and I’m not sure whether "::" counts as a function.

So I was wondering if anyone had any hints/ideas how to manually design said function? It just seems really hard when you can’t use any built-in functions and it has me stuck for quite some time now.

Asked By: NAstuden

||

Answers:

range and len are both built-in functions. Since list methods are accepted, you could do this with insert. It is reeaallyy slow* but it does the job for small lists without using any built-ins:

def rev(l):
    r = []
    for i in l:
        r.insert(0, i)
    return r

By continuously inserting at the zero-th position you end up with a reversed version of the input list:

>>> print(rev([1, 2, 3, 4]))
[4, 3, 2, 1]

Doing:

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

could also be considered a solution. ::-1 (:: has a different result) isn’t a function (it’s a slice) and [] is, again, a list method. Also, contrasting insert, it is faster and way more readable; just make sure you’re able to understand and explain it. A nice explanation of how it works can be found in this S.O answer.

*Reeaaalllyyyy slow, see juanpa.arrivillaga’s answer for cool plot and append with pop and take a look at in-place reverse on lists as done in Yoav Glazner’s answer.

Your example that works:

y = x[::-1]

uses Python slices notation which is not a function in the sense that I assume you’re requesting. Essentially :: acts as a separator. A more verbose version of your code would be:

y = x[len(x):None:-1]

or

y = x[start:end:step]

I probably wouldn’t be complaining that python makes your life really, really easily.


Edit to be super pedantic. Someone could argue that calling [] at all is using an inbuilt python function because it’s really syntactical sugar for the method __getitem__().

x.__getitem__(0) == x[0]

And using :: does make use of the slice() object.

x.__getitem__(slice(len(x), None, -1) == x[::-1]

But… if you were to argue this, anything you write in python would be using inbuilt python functions.

Answered By: SCB

:: is not a function, it’s a python literal. as well as []

How to check if ::, [] are functions or not. Simple,

    import dis
    a = [1,2]
    dis.dis(compile('a[::-1]', '', 'eval'))
      1           0 LOAD_NAME                0 (a)
                  3 LOAD_CONST               0 (None)
                  6 LOAD_CONST               0 (None)
                  9 LOAD_CONST               2 (-1)
                 12 BUILD_SLICE              3
                 15 BINARY_SUBSCR
                 16 RETURN_VALUE

If ::,[] were functions, you should find a label CALL_FUNCTION among python instructions executed by a[::-1] statement. So, they aren’t.

Look how python instructions looks like when you call a function, lets say list() function

>>> dis.dis(compile('list()', '', 'eval'))
  1           0 LOAD_NAME                0 (list)
              3 CALL_FUNCTION            0
              6 RETURN_VALUE

So, basically

def rev(f):
    return f[::-1]

works fine. But, I think you should do something like Jim suggested in his answer if your question is a homework or sent by you teacher. But, you can add this quickest way as a side note.

If you teacher complains about [::-1] notation, show him the example I gave you.

Answered By: levi

Here’s a solution that doesn’t use built-in functions but relies on list methods. It reverse in-place, as implied by your specification:

>>> x = [1,2,3,4]
>>> def reverse(seq):
...   temp = []
...   while seq:
...     temp.append(seq.pop())
...   seq[:] = temp
... 
>>> reverse(x)
>>> x
[4, 3, 2, 1]
>>> 

ETA

Jim, your answer using insert at position 0 was driving me nuts! That solution is quadratic time! You can use append and pop with a temporary list to achieve linear time using simple list methods. See (reverse is in blue, rev is green):

If it feels a little bit like “cheating” using seq[:] = temp, we could always loop over temp and append every item into seq and the time complexity would still be linear but probably slower since it isn’t using the C-based internals.

Answered By: juanpa.arrivillaga

Another way ( just for completeness 🙂 )

def another_reverse(lst):
    new_lst = lst.copy() # make a copy if you don't want to ruin lst...
    new_lst.reverse() # notice! this will reverse it in place
    return new_lst
Answered By: Yoav Glazner

Another way for completeness, range() takes an optional step parameter that will allow you to step backwards through the list:

def reverse_list(l):
    return [l[i] for i in range(len(l)-1, -1, -1)]
Answered By: kylieCatt

The most pythonic and efficient way to achieve this is by list slicing. And, since you mentioned you do not need any inbuilt function, it completely suffice your requirement. For example:

>>> def reverse_list(list_obj):
...     return list_obj[::-1]
...
>>> reverse_list([1, 3, 5 , 3, 7])
[7, 3, 5, 3, 1]
Answered By: Moinuddin Quadri

Just iterate the list from right to left to get the items..

a = [1,2,3,4]

def reverse_the_list(a):
   reversed_list = []
   for i in range(0, len(a)):
     reversed_list.append(a[len(a) - i - 1])
   return reversed_list

new_list = reverse_the_list(a)
print new_list
Answered By: SuperNova

Here’s a solution , using no in-built functions (not even len()) just loops

def reverse(L):

    i = 0
    j = -1
    for x in L:
        j+=1
    while i<j:
        L[i],L[j]=L[j],L[i]
        i+=1
        j-=1
    return L
Answered By: Andromedai
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.