0

I need to reverse a string without using the reverse function or [::-1].

My code so far is:

def reverse(text):
        if len(text) == 1:
        return text
    else:
        x= []
        y= ""
        for i in xrange(len(text)-1, -1, -1):
            x[len(text) - i] = text[i]
        for i in xrange(0,len(x)):
            y[i] = x[i]
        return y

The error I receive is "list assignment index out of range", although I am unsure why I am getting this. Thanks for any help.

Avinash Raj
  • 172,303
  • 28
  • 230
  • 274
user2958268
  • 67
  • 1
  • 4
  • 1
    Hint: if a list contains zero elements, you can't make it bigger by doing `x[0] = value`. – Kevin Feb 24 '15 at 16:21
  • 1
    Hint 2: You can't assign elements into a string. But you can use `''.join(somelist)` to join a list of strings into a string. – interjay Feb 24 '15 at 16:23
  • Hint 3: Use Hint 1 and Hint 2 – Daniel Feb 24 '15 at 16:26
  • 1
    Hint 4: This is a duplicate of [this post](http://stackoverflow.com/questions/18686860/reverse-a-string-in-python-without-using-reversed-or-1). – JonB Feb 24 '15 at 16:27

2 Answers2

1

Your reversed range logic is correct, start the range at the end of the string index and count down to 0, you just need to use it in a list comp and use join:

def reverse(text):
        # catch empty and strings of one char
        if len(text) < 2:
            return text
        # start at index of last char and decrease
        return "".join([text[i] for i in xrange(len(text)-1,-1,-1)])

You cannot assign to a string y[i] = x[i], if you wanted to do that you would need to make y a list and use again use join.

Your index error is because you are trying to index and empty list, you should append to x:

    for i in range(len(text)-1, -1, -1):
            x.append(text[i])

This would be how to do it with your own code although i would prefer just using join:

def reverse(text):
    if len(text) < 2:
       return text
    else:
        x= []
        y= ""
        for i in range(len(text)-1, -1, -1):
            x.append(text[i]) # append 
        for i in x: # iterate over x
            y += i # concatenate
        return y 

Which using join would be:

def reverse(text):
    if len(text) < 2:
       return text
    else:
        x= []
        for i in range(len(text)-1, -1, -1):
            x.append(text[i])
        return "".join(x)
Padraic Cunningham
  • 176,452
  • 29
  • 245
  • 321
0

You're doing a lot of funky things, including trying to assign to a list by a higher index and assuming it will "Fill in the blanks" as it were.

In [1]: x = []

In [2]: x[4] = 1

# what you want to happen:
# x = [None, None, None, None, 1]

# what actually happens:
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-2-a9f6d07b2ba4> in <module>()
----> 1 x[4] = 1

IndexError: list assignment index out of range

So let's take a different approach instead. What you really want to do is to take every character of the string and put them in the opposite order. Well lists have a pop method that removes and returns the last element, and an append element that adds to the end. That sounds about right. Luckily it's also really easy to turn a string into a list!

In [3]: s = "abcd"

In [4]: list(s)
Out[4]: ['a', 'b', 'c', 'd']

Now let's iterate through, poping and appending as we go, once per element in the new list.

In [5]: def new_reverse(s):
   ...:     in_ = list(s)
   ...:     out = []
   ...:     for _ in range(len(in_)):
   ...:         ch = in_.pop()
   ...:         out.append(s)
   ...:     return out
   ...:

In [6]: new_reverse("abcd")
Out[6]: ['d','c','b','a']

Well now we turned our string into a reversed list. That's the hard part, because joining lists back together into strings is really elementary. str has a join method that takes an iteratable and joins all the elements with the str calling it, e.g.

'|'.join(['a','b','c','d']) --> 'a|b|c|d'
'/'.join(['', 'usr', 'bin']) --> '/usr/bin'

If you use an empty string, '', this should all glob back together like normal.

In [12]: def new_reverse(s):
   ...:     in_ = list(s)
   ...:     out = []
   ...:     for _ in range(len(in_)):
   ...:         ch = in_.pop()
   ...:         out.append(s)
   ...:     return ''.join(out)
   ...:

In [13]: new_reverse('abcd')
Out[13]: 'dcba'
Adam Smith
  • 52,157
  • 12
  • 73
  • 112