PunyTitan
PunyTitan

Reputation: 277

How to unpack a nested list in python to sublists?

Assume that my list is:

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

After unpack, I want to get [1,2,3,4], [5], [6], [7]

How to do it with low time complexity?

Upvotes: 1

Views: 1056

Answers (5)

B. M.
B. M.

Reputation: 18628

You can just recursively check for good lists : good lists are those which don't contain lists. Each list is visited one time only.

def prettyflat(ll):
    pf=[]
    def good(ll):
        isgood = isinstance(ll,list) and  all([not good(l) for l in ll])
        if isgood : u.append(ll)
        return isgood
    good(ll)
    return pf

Output:[[1, 2, 3, 4], [5], [6], [7]]

Upvotes: 0

John La Rooy
John La Rooy

Reputation: 304137

Another way using regex:

>>> import re
>>> x = [[1, 2, 3, 4], [[[5], [6]], [7]]]
>>> eval(re.sub(r'([][])\1+', '\\1', str(x)))
([1, 2, 3, 4], [5], [6], [7])

@TigerhawkT3's answer is faster for this x, 28.9 µs per loop vs 41.8 µs per loop

so just for fun

import json
json.loads(re.sub(r'([][])\1+', '\\1', str(x)))

puts the regex back to 22.1 µs per loop

Upvotes: 2

Harsha Biyani
Harsha Biyani

Reputation: 7268

You can try :

>>> final_list = []
>>> def make_single(input_list):
    final_list_inside = []
    for i in input_list:
        if any(isinstance(el, list) for el in input_list):
            make_single(i)
        else:
            final_list_inside.append(i)
    if(len(final_list_inside) != 0):
        final_list.append(final_list_inside)


>>> make_single([[1, 2, 3, 4], [[[5], [6]], [7]]])
>>> final_list
[[1, 2, 3, 4], [5], [6], [7]]

Upvotes: 0

TigerhawkT3
TigerhawkT3

Reputation: 49320

The linked duplicate flattens an iterable completely. You just need a slight tweak to make the process stop one step earlier:

import collections
def flattish(l):
    for el in l:
        if isinstance(el, collections.Iterable) and not isinstance(el, str):
            if any(isinstance(e, collections.Iterable) for e in el):
                for sub in flattish(el):
                    yield sub
            else:
                    yield el
        else:
            yield [el]

The any(... will check if that iterable contains any iterables. This will flatten something like [1, [2, 3]], but leave [5] as-is. Additionally, the yield [el] ensures that any non-iterables will be contained in a list, so your result will be a list that contains only lists, some of which may have only a single element.

Upvotes: 3

vks
vks

Reputation: 67968

You can try using re.

import re
x=[ [1,2,3,4], [ [[5], [6]], [7] ]]
print map(lambda x:map(int,re.findall(r"\d+(?=.*\])",x)),re.findall(r"\[[^\[\]]*\]",str(x)))

Output:[[1, 2, 3, 4], [5], [6], [7]]

Upvotes: 0

Related Questions