WetenSchaap
WetenSchaap

Reputation: 55

Convert an irregular list with multiple levels of nested lists to a list of lists

I have some data in a messy nested list with many different (sub)-levels. I do not really care about these levels and just want the data in one big list of lists.

I've already looked for how to flatten a list of list or a nested list (for instance here, here and here), but solutions to those problems are not applicable here (I think).

So basically what I need is:

nested_list = [[[1, 2, 3], [[5, 6, 7], [8, 9, 10, 11, 23]]], [4], [[12, 13, 14], [[15, 16], [[17, 18], [19, 20]]]], [21, 22, 25, 26]]
unnested_list = nested_to_listoflist( nested_list )
#=> [ [1, 2, 3], [5, 6, 7], [8, 9, 10, 11, 23], [4], [12, 13, 14], [15, 16], [17, 18], [19, 20], [21, 22, 25, 26] ]

Any suggestions?

Upvotes: 2

Views: 383

Answers (5)

Booboo
Booboo

Reputation: 44148

Generator function flatten is passed a list and looks at each sublist. If the length of the sublist is 0 or if the first element of the sublist is not another list, it just yields the sublist as the next list to be added to the result. Otherwise it recursively processes the sublist. Function nested_to_listoflist just assembles all of the "yielded" lists into one final list.

def flatten(l):
    for el in l:
        if not el or not isinstance(el[0], list):
            yield el
        else:
            yield from flatten(el)

def nested_to_listoflist(l):
    return [el for el in flatten(l)]
    # or return list(flatten(l))


nested_list = [[[1, 2, 3], [[5, 6, 7], [8, 9, 10, 11, 23]]], [4], [[12, 13, 14], [[15, 16], [[17, 18], [19, 20]]]], [21, 22, 25, 26]]
unnested_list = nested_to_listoflist(nested_list)
print(unnested_list)

Prints:

[[1, 2, 3], [5, 6, 7], [8, 9, 10, 11, 23], [4], [12, 13, 14], [15, 16], [17, 18], [19, 20], [21, 22, 25, 26]]

Python Demo

Upvotes: 2

Masoud
Masoud

Reputation: 1280

You can use this recursive algorithm:

def flatten(l):
    result = []
    for item in l:
        if isinstance(item,list):
            if len(item)>0 and isinstance(item[0], list):
                result.extend(flatten(item))  #  recursion
            else:             
                result.append(item)
        else:
            result.append([item])   # decide what to do with stand_alone integers
    return result

nested_list = [[[1, 2, 3], [[5, 6, 7], [8, 9, 10, 11, 23]]], [], [[12, 13, 14], [[15, 16], [[17, 18], [19, 20]]]], [21, 22, 25, 26],3]
flattened_list = flatten(nested_list)

#  [[1, 2, 3], [5, 6, 7], [8, 9, 10, 11, 23], [], [12, 13, 14], [15, 16], [17, 18], [19, 20], [21, 22, 25, 26], [3]]

Upvotes: 0

Noam-N
Noam-N

Reputation: 914

Try this:

def nested_to_listoflist(nested_list):
    if len(nested_list) == 0 or not isinstance(nested_list[0], list):
        return [nested_list]

    unnested_list = []
    for l in nested_list:
        unnested_list += nested_to_listoflist(l)

    return unnested_list

Upvotes: 1

Ardweaden
Ardweaden

Reputation: 887

A funny way of doing it (not recommendable):

l = str(nested_l)
inner = False
new_l = "["

for i in range(2,len(l)):
    if l[i] == "]" and inner:
        inner = False
    elif l[i] == "[" and not inner:
        inner = True
    elif l[i] == "[" and inner or l[i] == "]" and not inner:
        continue
    new_l+=l[i]

new_l += "]"
new_l = eval(new_l)

Upvotes: 1

I think this will do the job for you,

open_ = []
open_.append(nested_list)
res = []
while len(open_) > 0:
    element = open_.pop()
    for item in element:
        if isinstance(item, list):
            open_.append(item)
        else:
            res.append(element)
            break

Upvotes: 1

Related Questions