user2144553
user2144553

Reputation: 105

Using (trying to) recursion to reverse lists within a list

def is_list(p):
    return isinstance(p, list)

def deep_reverse(p):
    initial = []
    for v, e in enumerate(p):
        if is_list(e):
            #print p[v][::-1]
            initial.append(p[v][::-1])
            deep_reverse(e)
    return initial

p = [1, [2, 3, [4, [5, 6, [7, 8]]]]]
print deep_reverse(p)

I get [[[4, [5, 6, [7, 8]]], 3, 2]], expected at least (I haven't bothered to figure out how to not lose the very first list [1[...]] yet) [[[[6, 5, [8, 7]], 4], 3, 2]].

As you can see the code only reverses [ [2, 3]] --> [[3, 2]]. What did I do wrong? Haven't I though about?

Upvotes: 2

Views: 1410

Answers (5)

Gareth Latty
Gareth Latty

Reputation: 88977

A more generic, Pythonic answer to this, based on Pavel Anossov's is as follows:

def deep_reversed(seq):
    return [deep_reversed(x) if (isinstance(x, collections.Sequence) and 
                                not isinstance(x, str)) else x 
            for x in reversed(seq)]

Note that this is for Python 3.x, in Python 2.x, you will want isinstance(x, basestring) instead to allow for Unicode strings.

This answer is a good one, as it will work correctly with any object that acts as a sequence - be it a list, a tuple, or a custom class. This means it's much more flexible.

Edit: If you wanted it to reverse strings internally:

def deep_reversed(seq):
    for x in reversed(seq):
        if isinstance(x, collections.Sequence):
            if isinstance(x, str):
                yield "".join(reversed(x))
            else:
                yield deep_reversed(x)
        else:
            yield x

Again, in 2.x, use isinstance(x, basestring).

Upvotes: 3

John La Rooy
John La Rooy

Reputation: 304137

In the recursive calls to deep_reverse(e) you are not using the returned value. It looks as though you are expecting it to modify the input list

You can change it to something like this:

def deep_reverse(p):
    initial = []
    for e in p[::-1]:
        if is_list(e):
            initial.append(deep_reverse(e)])
        else:
            initial.append(e)
    return initial

Upvotes: 2

GodMan
GodMan

Reputation: 2641

This will solve your purpose:

import collections
def dr(p):
     r=[]
     for i in p:
      if isinstance(i,collections.Iterable):
       r.append(dr(i))
      else:
       r.append(i)
     return r[::-1]

Upvotes: 1

HYRY
HYRY

Reputation: 97261

There are already many nice solutions, but maybe this is the algorithm you are trying:

def is_list(p):
    return isinstance(p, list)

def deep_reverse(p):
    initial = p[::-1] # reverse this level
    for v, e in enumerate(initial): 
        if is_list(e): # for all the sublist in this level
            initial[v] = deep_reverse(e) # recursively call deep_reverse to reverse the sublist
    return initial

p = [1, [2, 3, [4, [5, 6, [7, 8]]]]]
print deep_reverse(p)

Upvotes: 2

Pavel Anossov
Pavel Anossov

Reputation: 62868

This is how I would do it:

def deep_reverse(p):
    return [deep_reverse(x) if isinstance(x, list) else x for x in p[::-1]]

p = [1, [2, 3, [4, [5, 6, [7, 8]]]]]
print deep_reverse(p)   #  [[[[[8, 7], 6, 5], 4], 3, 2], 1]

Upvotes: 5

Related Questions