5487

I have a list of lists like

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

How can I flatten it to get [1, 2, 3, 4, 5, 6, 7, 8, 9]?


If your list of lists comes from a nested list comprehension, the problem can be solved more simply/directly by fixing the comprehension; please see How can I get a flat result from a list comprehension instead of a nested list?.

The most popular solutions here generally only flatten one "level" of the nested list. See Flatten an irregular (arbitrarily nested) list of lists for solutions that completely flatten a deeply nested structure (recursively, in general).

3

34 Answers 34

1
2
0

I like to add a high performant generator solution which can fatten nested lists (or any kind of iterable) of any depth not (only two-dimensional-lists):

from itertools import chain def flatten_deep_generator(iterable): iterator = iter(iterable) try: while 1: # StopIteration will break the loop item = next(iterator) # Check if item contains sub-items if not hasattr(item,'__trunc__'): iterator = chain(iter(item), iterator) else: yield item except StopIteration: pass 

Depending on your needs a generators have huge advantages over lists. E.g. If you want add filter() functions afterwards. The resulting list should be instanced only at the end after you have constructed the full generator incl. the filtering by this you avoid multiple iterations over the items.

Remark: Compared to the other proposed generator solution this is an iterative and not a recursive solution which avoids RecursionErrors in case of deep nested iterables.

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

2 Comments

what is the role of __trunc__ in this "high performant generator solution"? and why
The __trunc__ attribute is used to identify a numerical item or in other words a no more iterable item. It can be that we have some cornercases not covered then you must switch to the slower but more secured way: hastattr(item,'__iter__') or hasattr(item,'__next__') The solution should work on any iterable object so we cannot use a checlk like type(item) is list. E.g. the solution works on nested iterators, tuples and even strings would be flattend to single characters.
-1
import py_linq ls = [ [1, 2, 3], [4, 5, 6], [7], [8, 9] ] py_linq.Enumerable(ls).select_many() 

Comments

-1

Don't know if this applies to the OP's case. If you have some named lists to merge the unpacking operator * can be used effectively, e.g.,:

list_1 = list(range(10)) list_2 = list(range(10, 20)) list_3 = list(range(20, 30)) list_zero_to_twenty_nine = [*list_1, *list_2, *list_3] 

Comments

-3

Here is a recursive solution:

def lift_list(input_list): if input_list == []: return [] return lift_list(input_list[0]) + (lift_list(input_list[1:]) if len(input_list) > 1 else []) if isinstance(input_list, list) else [input_list] 

Note that this solution works also with subnested lists and singletons:

>>> lift_list([1, 2, [1,2,3], [1,2], [4, [5, [6]]], [3,4]]) ... [1, 2, 1, 2, 3, 1, 2, 4, 5, 6, 3, 4] 

2 Comments

Repeated list concatenation and slicing is massively, pointlessly inefficient.
I would do it like this: stackoverflow.com/a/2158532/707111
1
2

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.