Anthony Ifeanyi
Anthony Ifeanyi

Reputation: 53

Looping through List of nested List of lists

I have a nested list of lists occurring in the form of

 A = [[a,b],[c,d]] or [[[a,b],[c,d]]] or [[[[a,b],[c,d]]]] or [[[[[a,b],[c,d]]]]] 

and so on. These forms of A don't occur at the same time.

How can I code to peel the list, no matter how nested A may be, and obtain only:

[a,b] 
[c,d]

I tried this:

def Peel_list(Features):
    try:
        for lon,lat in Features:
            print((lon,lat))
    except:
        for Feature in Features:
            for t_list in Feature:
                for A in t_list:
                    for lon,lat in A:
                        print((lon,lat))
    return()

But it only works for limited A.

Upvotes: 4

Views: 609

Answers (5)

Ajax1234
Ajax1234

Reputation: 71451

You can use recursion with a generator:

def flatten(d):
   if all(not isinstance(i, list) for i in d):
      yield d
   else:
      for i in d:
         yield from flatten(i)

print(list(flatten([[[[['a', 'b'], ['c', 'd']]]]])))

Output:

[['a', 'b'], ['c', 'd']]

Upvotes: 0

Farzad Vertigo
Farzad Vertigo

Reputation: 2818

Here is another recursion based solution:

l1 = [[[['a','b'],['c','d'], [[1,2]]]]]
l2 = [[[[['a','b'],['c','d']]]]]

def f(inp):
    # you can skip this if statement if you are sure that there is no empty nested list 
    if not inp:
        return [[]]
    if (all(isinstance(element, list) for element in inp)):
        return [elem for x in inp for elem in f(x)]
    else:
        return [inp]

With all(), a condition can be checked on every element of an iterable. Results would be:

f(l1) #[['a', 'b'], ['c', 'd'], [1, 2]]
f(l2) #[['a', 'b'], ['c', 'd'], []]

Upvotes: 0

Samantha
Samantha

Reputation: 273

A simple approach for the cases that you've provided would be to have a while-loop that continually checks if the size of the list is 1 and modifies your list to contain only the single element (this would get rid of the outermost list).

x = [[[[[a,b],[c,d]]]]]
while len(x) == 1:
    x = x[0]

// result is x = [[1, 2], [3, 4]]

The general approach for when you have elements nested in an arbitrary number of lists would be Mitchel's answer.

Upvotes: 3

Desmond
Desmond

Reputation: 415

you can also try numpy ravel function on your list, output will be a 1D array.

Upvotes: 0

Mitch
Mitch

Reputation: 3418

Generally when we want to deal with a problem of arbitrarily nested objects recursion is a good place to start. Here we want to keep "digging down" until we hit the base case, in our case any non list value. The code looks something like this

test = [1, [3,4],[[5]], [[[6]]]]
peeled = []

def peel(myList, peeled):
    for val in myList:
        if isinstance(val, list):
            if not isinstance(val[0], list):
                peeled.append(val)
            else:
                peel(val, peeled)
        else:
            peeled.append(val)


peel(test, peeled)
print(peeled)

This will give you something like

[1, [3, 4], [5], [6]]

Upvotes: 4

Related Questions