Code Review Stack Exchange is a question and answer site for peer programmer code reviews. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

Reversing an array in Python without using a built-in function.

My solution looks like this:

def reverse(alist):
    end = len(alist)-1
    limit = int(end/2) + 1
    for i in range(limit):
        alist[i],alist[end] = alist[end],alist[i]
        end = end - 1
    return alist

print reverse([1,2,3,4,5,6])
share|improve this question
2  
One small question: Do you consider slices as being built-ins ? Or are you strictly speaking about the reversed() built-in ? If not, you could do def reverse(alist): return alist[::-1] – Dex' ter 12 hours ago
1  
@Dex'ter Yes, i am considering slice as built-ins here, also alist[::-1]. – Akan 12 hours ago
up vote 9 down vote accepted

The first solution that comes to mind is to take advantage of the powerful list comprehension and abuse the range function:

def reverse(some_list):
    return [some_list[n] for n in range(len(some_list) - 1, -1, -1)]

The above it's nothing more than the usual reversed for loop that you may find in other languages (like C / C++) as:

for (int i = array.length - 1; i >= 0; i--)  
{  
    // Do something ...  
}  

Details about the range function can be found here but basically, all you have to know about it is its prototype:

range(start, stop[, step])

which is very descriptive.

I'd go with this instead of your solution because it looks cleaner and I don't see any reasons of why it'd be slower or harder to understand.

share|improve this answer
    
+1 because this also does not modify the input list – Mark Omo 8 hours ago
    
Thanks!, This looks good. – Akan 4 hours ago

Calculating the limit is a tad annoying, because you have to carefully verify to not make an off-by-one error. It would be easier to loop until the indexes cross each other:

def reverse(alist):
    left = 0
    right = len(alist) - 1
    while left < right:
        alist[left], alist[right] = alist[right], alist[left]
        left += 1
        right -= 1

I made some other changes as well:

  • Adjusted formatting to follow PEP8
  • I renamed the index variables to more natural left, right
  • I dropped the return statement, because it might mislead users to assume that the returned list is a new list, which is not the case, because the function modifies the content of the input list.
share|improve this answer
    
Um, just tested this, and you get an IndexOutOfRange error. See the gist containing what I entered and the output – Thomas Ward 10 hours ago
2  
s/right += 1/right -= 1/. – Zeta 10 hours ago
1  
That fixes it, @Zeta. Now we just need Janos to update his code :P – Thomas Ward 10 hours ago
1  
Guys, don't be so shy to correct a typo ;-) – janos 9 hours ago
    
@janos fun fact it wouldn't let me :P Or I would have. – Thomas Ward 6 hours ago

Few stylistic points about your current solution:

  • use print() as a function for Python 3 compatibility
  • on the other hand, because you are running it on Python 2.x, you may avoid creating an extra list with range() and use xrange() function (differences)
  • according to PEP8, you need to have spaces around the operators
  • you can use end -= 1 shortcut instead of end = end - 1

The code with all the proposed changes applied:

def reverse(alist):
    end = len(alist) - 1
    limit = int(end / 2) + 1
    for i in xrange(limit):
        alist[i], alist[end] = alist[end], alist[i]
        end -= 1
    return alist

print(reverse([1, 2, 3, 4, 5, 6]))

Note that you don't have to return the alist from the function, since your reverse operates "in-place" - it modifies the input list. In other words, if you would remove return alist and run:

l = [1,2,3,4,5,6]
reverse(l)
print(l)

You would see [6, 5, 4, 3, 2, 1] printed.


One more way to do the reverse "manually" can be to use the negative indexing (not sure if it fits your constraints):

def reverse(alist):
    return [alist[-i] for i in range(1, len(alist) + 1)]

Or, an expanded version without a list comprehension:

def reverse(alist):
    newlist = []
    for i in range(1, len(alist) + 1):
        newlist.append(alist[-i])
    return newlist

Note that this is not working in place, it would return a new list.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.