Home > Mobile >  List reverse in particular range
List reverse in particular range

Time:10-27

I wanted to recursively reverse elements in the list for range i to j.

def revlist(l, i, j):
    if not l: # this will be true if l == []
        return l
    return l[-1:]   revlist(l[:-1]) # recursive case

For example list [1, 2, 3, 4, 5, 6, 7, 8, 9] for i = 2 and j = 5 will be [1, 5, 4, 3, 2, 6, 7, 8, 9].

How to do this?

CodePudding user response:

If you insist on a recursive implementation (which is inefficient, and rather pointless in this use case, as well as limiting the size of the list that can be reversed):

def rev_sublist(xs, i, j):
    def rec_rev(ys):
        if not ys:
            return ys
        else:
            return [ys[-1]]   rec_rev(ys[:-1])
    return xs[:i]   rec_rev(xs[i:j])   xs[j:]


print(rev_sublist([1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 5))

If you don't like the idea of the inner function here, the logic will become very convoluted, something like:

def rev_sublist(xs, i, j):
    if i >= j:
        return xs
    else:
        return rev_sublist(xs[:i]   [xs[j-1]]   xs[i:j-1]   xs[j:], i 1, j)


print(rev_sublist([1, 2, 3, 4, 5, 6, 7, 8, 9], 2, 5))

But if this was a programming class and I asked you to write a routine to reverse lists and you came up with this, I'm about to fail you.

Note: you say "in range i to j" - in Python, a range is generally not inclusive of j and list indexing starts at 0. So, in the above examples, the ouput would be:

[1, 2, 5, 4, 3, 6, 7, 8, 9]

This does not match your example that seems to want to include j and start indexing at 1, which would make your code extremely unpythonic and just wrong from my perspective as a professional software developer. But of course you could easily update the indices if you wanted to match that.

Also note that, the choice of 'range' is yours - for a function like rev_sublist I don't think making j inclusive is a bad idea - in fact, I'd probably prefer it.

Here's a solution without recursion (using the same convention as above):

def rev_sublist(xs, i, j):
    return xs[:i]   xs[j-1:i-1:-1]   xs[j:]

Which makes it pretty obvious why a recursive solution is a bad one.

If I were to write this function and the interface wasn't set in stone, I'd probably prefer:

def rev_sublist(xs, i, j):
    return xs[:i]   xs[j:i-1:-1]   xs[j 1:]

Which would return [1, 2, 6, 5, 4, 3, 7, 8, 9] for the above example. (also note that it's exactly the same as the solution independently proposed by user @MichaelM. which reinforces the idea that it's the more or less obvious implementation in Python)

CodePudding user response:

You don't need to use recursion here. Just use the built-in .reverse() method for a slice of the original list. You can do it like this:

def reverseSlice(lst, i, j):
    return lst[:i]   lst[j:i-1:-1]   lst[j 1:]


lst = [1, 2, 3, 4, 5]
print(reverseSlice(lst,  2, 4))  # => [1, 2, 5, 4, 3]
  • Related