1

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?

4
  • 2
    What have you already tried to do? Commented Oct 15, 2015 at 4:21
  • [s for sub in L for s in sub] Commented Oct 15, 2015 at 4:25
  • 1
    Possible duplicate of Flatten (an irregular) list of lists in Python Commented Oct 15, 2015 at 4:28
  • What is the expected outcome of unpacking [ [ 1, 2 ], 3 ] ? Commented Oct 15, 2015 at 4:34

5 Answers 5

3

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.

Sign up to request clarification or add additional context in comments.

1 Comment

This is the right way to do it. Don't use the regex hacks :)
2

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

1 Comment

Should I explain the regex or do people prefer to work it out themselves?
0

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]]

1 Comment

Nice idea, but what is the time complexity
0

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]]

Comments

0

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]]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.