How to make a flat list out of a list of lists?

Created 04.06.2009 20:30
Viewed 2.76M times
4047 votes

Is there a shortcut to make a simple list out of a list of lists in Python?

I can do it in a for loop, but maybe there is some cool "one-liner"? I tried it with functools.reduce()

from functools import reduce
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

but I get this error:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
4
Comments
Some other answers are better but the reason yours fails is that the 'extend' method always returns None. For a list with length 2, it will work but return None. For a longer list, it will consume the first 2 args, which returns None. It then continues with None.extend(<third arg>), which causes this erro by mehtunguh, 11.06.2013 21:48
There's an in-depth discussion of this here: rightfootin.blogspot.com/2006/09/more-on-python-flatten.html‌​, discussing several methods of flattening arbitrarily nested lists of lists. An interesting read! by RichieHindle, 04.06.2009 20:41
@shawn-chin solution is the more pythonic here, but if you need to preserve the sequence type, say you have a tuple of tuples rather than a list of lists, then you should use reduce(operator.concat, tuple_of_tuples). Using operator.concat with tuples seems to perform faster than chain.from_iterables with list. by Meitham, 06.10.2014 21:46
stackoverflow.com/questions/50259290/… (this article explain the difference between an np.flatten() and a tf.flatten() use (static vs dynamic) ndarray. by Golden Lion, 18.12.2020 16:48
Answers 50
32
5736

Given a list of lists t,

flat_list = [item for sublist in t for item in sublist]

which means:

flat_list = []
for sublist in t:
    for item in sublist:
        flat_list.append(item)

is faster than the shortcuts posted so far. (t is the list to flatten.)

Here is the corresponding function:

flatten = lambda t: [item for sublist in t for item in sublist]

As evidence, you can use the timeit module in the standard library:

$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in t for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(t, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,t)'
1000 loops, best of 3: 1.1 msec per loop

Explanation: the shortcuts based on + (including the implied use in sum) are, of necessity, O(T**2) when there are T sublists -- as the intermediate result list keeps getting longer, at each step a new intermediate result list object gets allocated, and all the items in the previous intermediate result must be copied over (as well as a few new ones added at the end). So, for simplicity and without actual loss of generality, say you have T sublists of k items each: the first k items are copied back and forth T-1 times, the second k items T-2 times, and so on; total number of copies is k times the sum of x for x from 1 to T excluded, i.e., k * (T**2)/2.

The list comprehension just generates one list, once, and copies each item over (from its original place of residence to the result list) also exactly once.

04.06.2009 20:37
Comments
I tried a test with the same data, using itertools.chain.from_iterable : $ python -mtimeit -s'from itertools import chain; l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'list(chain.from_iterable(l))'. It runs a bit more than twice as fast as the nested list comprehension that's the fastest of the alternatives shown here. by intuited, 15.10.2010 01:21
I found the syntax hard to understand until I realized you can think of it exactly like nested for loops. for sublist in l: for item in sublist: yield item by Rob Crowell, 27.07.2011 16:43
@intuited your solution actually returns an iterator, not an actual list - that's why it runs twice as fast. see type(itertools.chain([ [1,2], [3,4] ])). but if @emma needs the nested list just to iterate over it - that's a fine and optimal solution :o) by Boris Chervenkov, 19.05.2012 21:59
@BorisChervenkov: Notice that I wrapped the call in list() to realize the iterator into a list. by intuited, 20.05.2012 22:56
numpy.concatenate seems a bit faster than any of the methods here, if you are willing to accept an array. by Makoto, 19.07.2012 08:04
Doesn't universally work! l=[1,2,[3,4]] [item for sublist in l for item in sublist] TypeError: 'int' object is not iterable by Sven, 27.03.2013 14:00
@Noio It makes sense if you re-order it: [item for item in sublist for sublist in l ]. Of course, if you re-order it, then it won't make sense to Python, because you're using sublist before you defined what it is. by Mark E. Haase, 23.05.2013 22:29
[leaf for tree in forest for leaf in tree] might be easier to comprehend and apply. by John Mee, 29.08.2013 01:38
@Sven It works for any list of lists; [1,2,[3,4]] is not a list of lists. You could hack together a one-line solution for that particular case with something like: [item for sublist in [sublist if isinstance(sublist, list) else [sublist] for sublist in l] for item in sublist]; but that's not concise enough to be worth fitting into one line. Alternatively, it's simple enough to write yourself a function for flattening arbitrarily nested sequences; see also stackoverflow.com/a/2158532/2359271 by Air, 03.10.2013 17:51
@wim I really just write the for loop structure out in full if i'm not sure what a list comprehension is doing. Though I will grant that at face value item for sublist in l for item in sublist sounds like nonsense. by Cruncher, 08.10.2013 13:18
the reduce example in the main text use the + operator, and therefore create N list. reduce(lambda x, y : x.extend(y) or x, ll, []) is much faster than list comprehension in my test. The tricky part is the expression : x.extend(y) return None, so we use or to get the accumulator list extended : a or b return b if bool(a) evaluate to false. by LBarret, 14.05.2014 19:21
@AlexMartelli Can you suggest whether this would still be the best option if all sublists are the same length (in my case length 2)? by Joel, 04.01.2015 12:55
@Joel, actually nowadays list(itertools.chain.from_iterable(l)) is best -- as noticed in other comments and Shawn's answer. by Alex Martelli, 04.01.2015 15:40
My attempt to understand [item**,** for sublist in l-> for item in sublist] by Oren, 12.02.2015 11:57
Really nice illustration! The versions based on sum/reduce fall victim to Schlemiel the Painter's algorithm, an antipattern named as such by Stack Overflow's founder Joel Spolsky :) by Dan Lenski, 11.07.2015 05:19
Sorry to revive this very old thread, but I was curious why this solution is the best. If I'm reading the timeit output correctly, each loop of this solution runs roughly 10 times faster, but 10 times more loops are required. by JuanXarg, 26.08.2015 13:06
@JuanXarg, nope, you're totally misunderstanding timeit's output: it iterates 10 more times because it can (within the rough constraint of taking about the same amount of elapsed time), not because the iterations are in any way, shape, or form, "required". by Alex Martelli, 28.08.2015 21:50
Any sublist that is not actually a list but an str would get split too, anyway to dodge that in a pythonic way? by Hamza Ouaghad, 10.06.2016 18:13
I don't care about how fast it runs as long as it's hard to understand!!! Can anyone tell me he/she can remember the syntax 3 months later without referring to this same post again? Can anyone tell me why you need to repeat item for sublist? Ugly Ugly Ugly!! by Kenneth Jiang, 28.09.2016 18:38
Why all the upvotes? reduce(operator.concat, list2d) is faster AND easier to understand! See this answer. by ChaimG, 30.10.2016 02:29
I have tried to put parentheses to clarify the associativity of these (nested?) generators.. but I fail so far. None of list(i for a in ([[1, 2], [3, 4]] for i in a)) and list((i for a in [[1, 2], [3, 4]]) for i in a) compile, but give syntax errors. I understand that the latest a refers to the first a introduced there. So I assumed that the expression must be left-associative. But the latter fails to parse aswell. Any hint to this? by Johannes Schaub - litb, 09.01.2017 18:02
@KennethJiang I find it is extremely easy to memorize. Just use: [x for x in x for x in x]. It became one of my favorites :D by Someone, 10.03.2017 14:25
@JohnMee: [leaf for leaf in tree for tree in forest] would have been even better and much easier to read but sadly, Python devs didn't think so. by Eric Duminil, 15.04.2017 16:06
@intuited evaluating efficency on a list of 99 items hardly amounts to a true benchmark by MichaelChirico, 30.06.2017 13:41
At first the [leaf for tree in forest for leaf in tree] syntax seems confusing and in the wrong order, but its the same as a nested for loop, except the yield leaf is moved to the front so it fits the list comprehension standard. e.g. for tree in forest: for leaf in tree: yield leaf . The other suggested syntax order [leaf for leaf in tree for tree in forest] seems much more like piping or composition rather than nesting so yeah from that perspective it's easier to reason about that deep nesting. by Davos, 12.09.2017 03:42
I wish there were something like R's magrittr package for piping functions together in Python. It's generally easier to read from left to right rather than from inside out, although perhaps that's a very biased perspective from someone who natively writes a left-to-right language like English. by Davos, 12.09.2017 03:51
@AlexMartelli You said "nowadays list(itertools.chain.from_iterable(l)) is best". Can you add that to the top of your answer, with a link to a better answer? Your answer has so many upvotes that it seems authoritative! by Neal Gokli, 01.08.2018 20:26
Just to add, the reason why we write the list comprehension in such a way is because it solves the 'undefined variable" problem. So, when working with list comprehension you can think of writing this as [ item for item in sublist for sublist in list] which might make more sense, but sadly will result in error. Since ''sublist'' hasn't been defined before, u cant really iterate. So you take the same list comprehension, and swap the for loops (bring the second one before the first one) resulting in - [ item for sublist in list for item in sublist ] by Akshay Sehgal, 07.04.2019 20:05
This solution does not work it you have a list of lists of lists of lists of lists... by Samuel Muldoon, 06.11.2019 20:32
Does this type of for expression have a name, so I can find it in the documentation? by galactikuh, 10.06.2020 17:59
@galactikuh list comprehension --- why doesnt print([item for item in sublist for sublist in list_of_lists]) work? undefined name sublist by Ridhwaan Shakeel, 14.01.2021 17:28
why 2 for loops. it can be achieved in 1. data = list() l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] for result in l: data+=result by Siddharth Chabra, 27.04.2021 05:34
Show remaining 27 comments
5
1822

You can use itertools.chain():

import itertools

list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain(*list2d))

Or you can use itertools.chain.from_iterable() which doesn't require unpacking the list with the * operator:

merged = list(itertools.chain.from_iterable(list2d))
04.06.2009 21:06
Comments
The * is the tricky thing that makes chain less straightforward than the list comprehension. You have to know that chain only joins together the iterables passed as parameters, and the * causes the top-level list to be expanded into parameters, so chain joins together all those iterables, but doesn't descend further. I think this makes the comprehension more readable than the use of chain in this case. by Tim Dierks, 03.09.2014 14:13
@TimDierks: I'm not sure "this requires you to understand Python syntax" is an argument against using a given technique in Python. Sure, complex usage could confuse, but the "splat" operator is generally useful in many circumstances, and this isn't using it in a particularly obscure way; rejecting all language features that aren't necessarily obvious to beginning users means you're tying one hand behind your back. May as well throw out list comprehensions too while you're at it; users from other backgrounds would find a for loop that repeatedly appends more obvious. by ShadowRanger, 12.11.2015 20:26
This answer, and other answers here, give incorrect result if the top level also contains a value. for instance, list = [["abc","bcd"],["cde","def"],"efg"] will result in an output of ["abc", "bcd", "cde", "def", "e", "f", "g"]. by gouravkr, 01.01.2020 10:39
It seems * operator can not be used in python2 by wkm, 05.06.2020 10:17
@gouravkr that's right, but here, the string is much less of a value than it is an iterable. The question is about lists of lists, so indeed any other iterable in the parent list is not guaranteed to work. Lists (as homogeneous data structures) most often hold items of equal type anyway, so maybe tuples are more suitable in your use case. by Alex Povel, 02.07.2020 14:35
16
1036

Note from the author: This is inefficient. But fun, because monoids are awesome. It's not appropriate for production Python code.

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

This just sums the elements of iterable passed in the first argument, treating second argument as the initial value of the sum (if not given, 0 is used instead and this case will give you an error).

Because you are summing nested lists, you actually get [1,3]+[2,4] as a result of sum([[1,3],[2,4]],[]), which is equal to [1,3,2,4].

Note that only works on lists of lists. For lists of lists of lists, you'll need another solution.

04.06.2009 20:35
Comments
that's pretty neat and clever but I wouldn't use it because it's confusing to read. by andrewrk, 15.06.2010 18:55
This is a Shlemiel the painter's algorithm joelonsoftware.com/articles/fog0000000319.html -- unnecessarily inefficient as well as unnecessarily ugly. by Mike Graham, 25.04.2012 18:24
The append operation on lists forms a Monoid, which is one of the most convenient abstractions for thinking of a + operation in a general sense (not limited to numbers only). So this answer deserves a +1 from me for (correct) treatment of lists as a monoid. The performance is concerning though... by ulidtko, 03.12.2014 10:35
@andrewrk Well, some people think that this is the cleanest way of doing it : youtube.com/watch?v=IOiZatlZtGU the ones who do not get why this is cool just need to wait a few decades until everybody does it this way :) let's use programming languages (and abstractions) that are discovered and not invented, Monoid is discovered. by jhegedus, 05.10.2015 08:51
this is a very inefficient way because of the quadratic aspect of the sum. by Jean-François Fabre, 31.07.2017 18:04
This article explains the maths of the inefficiency mathieularose.com/how-not-to-flatten-a-list-of-lists-in-pyth‌​on by ds4940, 04.01.2018 16:46
This doesn't seem to work in python 2.7, unless I'm doing something wrong. When I'm dealing with strings: TypeError: can only concatenate list (not "str") to list When I change it to ints, I get the same error but s/str/int/. I was assuming 'sum' is a standard operator... ? by isaaclw, 08.02.2018 20:04
So.. this is perfectly fine for short cases, then? by naught101, 20.02.2018 01:28
@isaaclw then put a '' instead of a [] by whackamadoodle3000, 18.07.2018 12:12
@ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000 no, sum is protected against string summing. You have to use str.join by Jean-François Fabre, 25.08.2018 13:44
Note that this doesn't work in every situation. You may have to do sum(l+[[]]) instead by mortonjt, 29.10.2018 22:22
@jhegedus "let's use programming languages that are discovered and not invented" and yet here you are, using Python. People prefer things designed for people. by Boris, 24.03.2020 18:15
@Boris that wasn't his quote. by Triptych, 25.03.2020 18:10
@Triptych how does that affect what I said? by Boris, 25.03.2020 19:57
Update to this: since Python 3.8, you can now use sum(l, start=[]) now, which is much clearer. by Tushar Sadhwani, 28.04.2020 20:11
As a functional programmer, I don’t understand why you’d find that ugly or unclear : in python, summing two lists concatenate them. So I find that using sum on a list of lists is the most intuitive approach to concatenating all elements of said list… (Tho it is inneficient) by Nephanth, 19.06.2020 09:56
Show remaining 11 comments
6
631

I tested most suggested solutions with perfplot (a pet project of mine, essentially a wrapper around timeit), and found

import functools
import operator
functools.reduce(operator.iconcat, a, [])

to be the fastest solution, both when many small lists and few long lists are concatenated. (operator.iadd is equally fast.)

enter image description here

enter image description here


Code to reproduce the plot:

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)
26.07.2017 09:38
Comments
For huge nested lists,' list(numpy.array(a).flat)' is the fastest among all functions above. by Sara, 20.01.2019 13:57
Tried using regex: 'list(map(int, re.findall(r"[\w]+", str(a))))'. Speed is bit slower that numpy_concatenate by Justas, 14.10.2019 08:05
Is there a way to do a 3-d perfplot? number of arrays by average size of array? by Leo, 30.04.2020 00:31
I love your solution. Short, simple, and efficient :-) by Chadee Fouad, 29.05.2020 07:00
@Sara can you define "huge" please? by Boris, 14.11.2020 06:05
Tried numpy_flat on the test example from Rossetta Code (link) and got VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray by mirekphd, 05.12.2020 11:08
Show remaining 1 comments
4
257

Don't reinvent the wheel

If you use -

...Django:

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

...Pandas:

>>> from pandas.core.common import flatten
>>> list(flatten(l))

...Itertools:

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

...Matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

...Unipath:

>>> from unipath.path import flatten
>>> list(flatten(l))

...Setuptools:

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
26.07.2019 18:34
Comments
flatten = itertools.chain.from_iterable should be the right answer by geckos, 26.08.2019 00:57
great answer! works also for l=[[[1, 2, 3], [4, 5]], 5] in the case of pandas by Markus Dutschke, 11.09.2019 08:28
I like the Pandas solution. If you have something like: list_of_menuitems = [1, 2, [3, [4, 5, [6]]]], it will result on: [1, 2, 3, 4, 5, 6]. What I miss is the flatten level. by imjoseangel, 20.02.2020 10:14
All these great libraries reinvented the wheel, why shouldn't I? by Nathan Chappell, 03.08.2020 06:51
9
222
>>> from functools import reduce
>>> l = [[1,2,3], [4,5,6], [7], [8,9]]
>>> reduce(lambda x, y: x+y, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

The extend() method in your example modifies x instead of returning a useful value (which functools.reduce() expects).

A faster way to do the reduce version would be

>>> import operator
>>> l = [[1,2,3], [4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
04.06.2009 20:35
Comments
reduce(operator.add, l) would be the correct way to do the reduce version. Built-ins are faster than lambdas. by agf, 24.09.2011 10:04
@agf here is how: * timeit.timeit('reduce(operator.add, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000) 0.017956018447875977 * timeit.timeit('reduce(lambda x, y: x+y, l)', 'import operator; l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]', number=10000) 0.025218963623046875 by lukmdo, 20.03.2012 22:13
This is a Shlemiel the painter's algorithm joelonsoftware.com/articles/fog0000000319.html by Mike Graham, 25.04.2012 18:26
this can use only for integers. But what if list contains string? by Freddy, 11.09.2015 07:16
@Freddy: The operator.add function works equally well for both lists of integers and lists of strings. by Greg Hewgill, 11.09.2015 07:38
I tried reduce with operator.concat on a list of 1,000,000 integer sublists of lengths 1-10, and it never returned (after 1 minute). The list comprehension, operator.itertools and a simple list.extend over loop all returned in sub-seconds. The last method was the fastest! by Rupen B, 10.02.2019 02:31
reduce() will fail if l = [[1,2,3], [4,5,6], [7], [8,9], [1,[2,3]]]. Use pandas.flatten() or similar instead. by Goujon, 25.08.2020 14:30
reduce also fails when all elements are not list. (e.g. l=[1, [2,3]]) by Sajad.sni, 08.09.2020 08:21
reduce is very inefficient for this use case as it will repeat copies and generate many unused temporary lists (O(n^2) in both time and possibly space, depending on how the GC decides to clean). It's better to use append or extend. by gntskn, 02.10.2020 17:00
Show remaining 4 comments
7
132

Here is a general approach that applies to numbers, strings, nested lists and mixed containers.

Code

#from typing import Iterable 
from collections import Iterable                            # < py38


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

Notes:

  • In Python 3, yield from flatten(x) can replace for sub_x in flatten(x): yield sub_x
  • In Python 3.8, abstract base classes are moved from collection.abc to the typing module.

Demo

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

Reference

  • This solution is modified from a recipe in Beazley, D. and B. Jones. Recipe 4.14, Python Cookbook 3rd Ed., O'Reilly Media Inc. Sebastopol, CA: 2013.
  • Found an earlier SO post, possibly the original demonstration.
29.11.2016 04:14
Comments
I just wrote pretty much the same, because I didn't see your solution ... here is what I looked for "recursively flatten complete multiple lists" ... (+1) by Martin Thoma, 25.03.2017 15:32
@MartinThoma Much appreciated. FYI, if flattening nested iterables is a common practice for you, there are some third-party packages that handle this well. This may save from reinventing the wheel. I've mentioned more_itertools among others discussed in this post. Cheers. by pylang, 25.03.2017 17:51
Maybe traverse could also be a good name for this way of a tree, whereas I'd keep it less universal for this answer by sticking to nested lists. by Wolf, 15.06.2017 10:22
You can check if hasattr(x, '__iter__') instead of importing/checking against Iterable and that will exclude strings as well. by Ryan Allen, 30.04.2018 16:46
the above code doesnt seem to work for if one of the nested lists is having a list of strings. [1, 2, [3, 4], [4], [], 9, 9.5, 'ssssss', ['str', 'sss', 'ss'], [3, 4, 5]] output:- [1, 2, 3, 4, 4, 9, 9.5, 'ssssss', 3, 4, 5] by sunnyX, 12.06.2019 21:35
@sunnyX It seems to work when I try your input, even with a deeply nested list of strings, e.g. list(flatten([["a", "b", ["c", "d", ["e", "f", ["g"]]]]])) -> ['a', 'b', 'c', 'd', 'e', 'f', 'g']. What version of Python are you using? by pylang, 12.06.2019 22:52
@pylang Python 3.6.2 by sunnyX, 13.06.2019 13:53
Show remaining 2 comments
3
63

If you want to flatten a data-structure where you don't know how deep it's nested you could use iteration_utilities.deepflatten1

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

It's a generator so you need to cast the result to a list or explicitly iterate over it.


To flatten only one level and if each of the items is itself iterable you can also use iteration_utilities.flatten which itself is just a thin wrapper around itertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Just to add some timings (based on Nico Schlömer answer that didn't include the function presented in this answer):

enter image description here

It's a log-log plot to accommodate for the huge range of values spanned. For qualitative reasoning: Lower is better.

The results show that if the iterable contains only a few inner iterables then sum will be fastest, however for long iterables only the itertools.chain.from_iterable, iteration_utilities.deepflatten or the nested comprehension have reasonable performance with itertools.chain.from_iterable being the fastest (as already noticed by Nico Schlömer).

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 Disclaimer: I'm the author of that library

26.11.2016 00:20
Comments
sum no longer works on arbitrary sequences as it starts with 0, making functools.reduce(operator.add, sequences) the replacement (aren't we glad they removed reduce from builtins?). When the types are known it might be faster to use type.__add__. by Yann Vernier, 14.05.2018 06:29
@YannVernier Thanks for the information. I thought I ran these benchmarks on Python 3.6 and it worked with sum. Do you happen to know on which Python versions it stopped working? by MSeifert, 15.05.2018 09:24
I was somewhat mistaken. 0 is just the default starting value, so it works if one uses the start argument to start with an empty list... but it still special cases strings and tells me to use join. It's implementing foldl instead of foldl1. The same issue pops up in 2.7. by Yann Vernier, 15.05.2018 09:31
3
41

Why do you use extend?

reduce(lambda x, y: x+y, l)

This should work fine.

04.06.2009 20:38
Comments
for python3 from functools import reduce by andorov, 19.01.2017 18:15
Sorry that's really slow see rest of answers by Mr_and_Mrs_D, 29.05.2017 12:04
This is by far the easiest to understand yet short solution that works on Python 2 and 3. I realise that a lot of Python folks are in data processing where there's huge amounts of data to process and thus care a lot about speed, but when you are writing a shell script and only have a few dozen elements in a few sub-lists, then this is perfect. by Asfand Qazi, 07.09.2018 13:36
1
45

I take my statement back. sum is not the winner. Although it is faster when the list is small. But the performance degrades significantly with larger lists.

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
    ).timeit(100)
2.0440959930419922

The sum version is still running for more than a minute and it hasn't done processing yet!

For medium lists:

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
20.126545906066895
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
22.242258071899414
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
16.449732065200806

Using small lists and timeit: number=1000000

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
2.4598159790039062
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.5289170742034912
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.0598428249359131
04.06.2009 20:46
Comments
for a truly miniscule list, e.g. one with 3 sublists, maybe -- but since sum's performance goes with O(N**2) while the list comprehension's goes with O(N), just growing the input list a little will reverse things -- indeed the LC will be "infinitely faster" than sum at the limit as N grows. I was responsible for designing sum and doing its first implementation in the Python runtime, and I still wish I had found a way to effectively restrict it to summing numbers (what it's really good at) and block the "attractive nuisance" it offers to people who want to "sum" lists;-). by Alex Martelli, 04.06.2009 21:07
2
44

There seems to be a confusion with operator.add! When you add two lists together, the correct term for that is concat, not add. operator.concat is what you need to use.

If you're thinking functional, it is as easy as this::

>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

You see reduce respects the sequence type, so when you supply a tuple, you get back a tuple. Let's try with a list::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

Aha, you get back a list.

How about performance::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

from_iterable is pretty fast! But it's no comparison to reduce with concat.

>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
14.09.2016 15:09
Comments
Hmm to be fair second example should be list also (or first tuple ?) by Mr_and_Mrs_D, 28.05.2017 13:20
Using such small inputs isn't much of a fair comparison. For 1000 sequences of length 1000, I get 0.037 seconds for list(chain.from_iterable(...)) and 2.5 seconds for reduce(concat, ...). The problem is that reduce(concat, ...) has quadratic runtime, whereas chain is linear. by kaya3, 18.12.2019 20:38
3
37

Consider installing the more_itertools package.

> pip install more_itertools

It ships with an implementation for flatten (source, from the itertools recipes):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

Note: as mentioned in the docs, flatten requires a list of lists. See below on flattening more irregular inputs.


As of version 2.4, you can flatten more complicated, nested iterables with more_itertools.collapse (source, contributed by abarnet).

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
02.12.2016 18:35
Comments
If you can afford adding a package to your project - this answer is best by viddik13, 05.03.2020 15:53
it fails when all elements are not list. (e.g. lst=[1, [2,3]]). of course integer is not iterable. by Sajad.sni, 08.09.2020 08:32
also, mind that list of strings will be flattened to a list of characters by viddik13, 30.10.2020 02:05
2
28

The reason your function didn't work is because the extend extends an array in-place and doesn't return it. You can still return x from lambda, using something like this:

reduce(lambda x,y: x.extend(y) or x, l)

Note: extend is more efficient than + on lists.

04.06.2009 20:47
Comments
extend is better used as newlist = [], extend = newlist.extend, for sublist in l: extend(l) as it avoids the (rather large) overhead of the lambda, the attribute lookup on x, and the or. by agf, 24.09.2011 10:12
for python 3 add from functools import reduce by Markus Dutschke, 02.07.2019 12:24
1
23

Recursive version

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

def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):

            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)

            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]
14.12.2018 10:51
Comments
nice, no imports needed and it's clear as to what it's doing ... flattening a list, period :) by Goran B., 25.06.2019 08:46
0
21

The accepted answer did not work for me when dealing with text-based lists of variable lengths. Here is an alternate approach that did work for me.

l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]

Accepted answer that did not work:

flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']

New proposed solution that did work for me:

flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']
24.09.2018 02:08
1
23
def flatten(l, a):
    for i in l:
        if isinstance(i, list):
            flatten(i, a)
        else:
            a.append(i)
    return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

# [1, 1, 1, 3, 4, 5, 2, 3, 4, 5, 6]
26.10.2016 01:12
Comments
def flatten(l, a=None): if a is None: a = [] [...] by Poik, 22.02.2018 23:28
1
22

A bad feature of Anil's function above is that it requires the user to always manually specify the second argument to be an empty list []. This should instead be a default. Due to the way Python objects work, these should be set inside the function, not in the arguments.

Here's a working function:

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []

    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

Testing:

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]
11.11.2016 11:53
Comments
instead of a=None and if statement you could use a=[] by Rocket Nikita, 10.02.2021 13:57
1
16

Following seem simplest to me:

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]
05.07.2017 05:14
Comments
Doesn't work for lists with different dimensions. -1 by nurub, 20.01.2020 16:33
1
13

One can also use NumPy's flat:

import numpy as np
list(np.array(l).flat)

Edit 11/02/2016: Only works when sublists have identical dimensions.

17.07.2016 12:57
Comments
would that be the optimal solution ? by RetroCode, 22.09.2016 20:08
0
17

matplotlib.cbook.flatten() will work for nested lists even if they nest more deeply than the example.

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

Result:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

This is 18x faster than underscore._.flatten:

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636
01.02.2018 18:22
1
5

Fastest solution I have found (for large list anyway):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

Done! You can of course turn it back into a list by executing list(l)

28.11.2016 21:09
Comments
This is wrong, flatten will reduce the dimensions of the nd array to one, but not concatenate the lists inside as one. by Ando Jurai, 30.06.2017 08:15
1
9

I personally find it hard to remember all the modules that needed to be imported. Thus I tend to use a simple method, even though I don't know how its performance is compared to other answers.

If you just want to flatten nested lists, then the following will do the job:

def flatten(lst):
    for item in lst:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

# test case:
a =[0, [], "fun", [1, 2, 3], [4, [5], 6], 3, [7], [8, 9]]
list(flatten(a))
# output 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]

However, if you want to flatten a list of iterables (list and/or tuples), it can also do the job with a slight modification:

from collections.abc import Iterable
def flatten(lst):
    for item in lst:
        if isinstance(item,Iterable) and not isinstance(item,str):
            yield from flatten(item)
        else:
            yield item

# test case:
a =[0, [], "fun", (1, 2, 3), [4, [5], (6)], 3, [7], [8, 9]]
list(flatten(a))
# output: 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]
21.07.2020 17:13
Comments
I like this one, it works no matter how many dimensions the list has. by Max, 22.12.2020 21:52
0
7

you can use list extend method, it shows to be the fastest:

flat_list = []
for sublist in l:
    flat_list.extend(sublist)

performance:

import functools
import itertools
import numpy
import operator
import perfplot



def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def extend(a):
    n = []

    list(map(n.extend, a))

    return n 


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        functools_reduce_iconcat, extend,itertools_chain, numpy_flat
        ],
    n_range=[2**k for k in range(16)],
    xlabel='num lists',
    )

output:enter image description here

25.01.2020 21:08
2
6

You can use numpy :
flat_list = list(np.concatenate(list_of_list))

24.07.2018 09:11
Comments
This works for numerical, strings and mixed lists also by Nitin, 19.09.2018 07:53
Fails for unevenly nested data, like [1, 2, [3], [[4]], [5, [6]]] by EL_DON, 22.04.2019 21:32
4
5

Simple code for underscore.py package fan

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

It solves all flatten problems (none list item or complex nesting)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

You can install underscore.py with pip

pip install underscore.py
25.03.2017 05:09
Comments
Similarly, you can use pydash. I find this version to be much more readable than the list comprehension or any other answers. by gliemezis, 06.06.2017 03:22
This is super slow. by Nico Schlömer, 26.07.2017 09:52
Why does it have a module named _? That seems like a bad name. See stackoverflow.com/a/5893946/6605826 by EL_DON, 20.07.2018 18:04
@EL_DON: From underscore.py readme page "Underscore.py is a python port of excellent javascript library underscore.js". I think it's the reason for this name. And yes, It's not a good name for python by Vu Anh, 21.07.2018 02:26
2
2

another fun way to do this:

from functools import reduce
from operator import add

li=[[1,2],[3,4]]
x= reduce(add, li)
28.08.2019 08:09
Comments
If by "fun" you mean slow and not properly handling input like li=[ [1,2,3], 4, [5, 6], "foo" ]. ;-) by Mitch McMabers, 07.11.2019 06:54
@MitchMcMabers by "fun" as in another snippet of code which runs on the sample input as shared by the OP. The nerd me never claimed speed as a value add. Happy to receive your "down vote" :) by sudeepgupta90, 07.11.2019 09:39
1
7
from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)

The advantage of this solution over most others here is that if you have a list like:

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

while most other solutions throw an error this solution handles them.

30.09.2019 10:49
Comments
The question states a "list of lists", but your example list includes a non-list item. Most other solutions are sticking to the original question. Your solution solves a wider problem, but it also requires a non-base Python package (nltk) that must be installed first. by simonobo, 14.04.2020 08:55
1
5

If you are willing to give up a tiny amount of speed for a cleaner look, then you could use numpy.concatenate().tolist() or numpy.concatenate().ravel().tolist():

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

You can find out more here in the docs numpy.concatenate and numpy.ravel

27.10.2016 03:24
Comments
Doesn't work for unevenly nested lists like [1, 2, [3], [[4]], [5, [6]]] by EL_DON, 22.04.2019 21:39
1
6

Note: Below applies to Python 3.3+ because it uses yield_from. six is also a third-party package, though it is stable. Alternately, you could use sys.version.


In the case of obj = [[1, 2,], [3, 4], [5, 6]], all of the solutions here are good, including list comprehension and itertools.chain.from_iterable.

However, consider this slightly more complex case:

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

There are several problems here:

  • One element, 6, is just a scalar; it's not iterable, so the above routes will fail here.
  • One element, 'abc', is technically iterable (all strs are). However, reading between the lines a bit, you don't want to treat it as such--you want to treat it as a single element.
  • The final element, [8, [9, 10]] is itself a nested iterable. Basic list comprehension and chain.from_iterable only extract "1 level down."

You can remedy this as follows:

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

Here, you check that the sub-element (1) is iterable with Iterable, an ABC from itertools, but also want to ensure that (2) the element is not "string-like."

01.02.2018 18:33
Comments
If you are still interested in Python 2 compatibility, change yield from to a for loop, e.g. for x in flatten(i): yield x by pylang, 19.06.2018 19:06
7
2

Another unusual approach that works for hetero- and homogeneous lists of integers:

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]
09.01.2018 14:34
Comments
That's just a more complicated and a bit slower way of what ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000 already posted before. I reinvented his proposal yesterday, so this approach seems quite popular these days ;) by Darkonaut, 10.01.2018 22:03
Not quite: wierd_list = [[1, 2, 3], [4, 5, 6], [7], [8, 9], 10] >> nice_list=[1, 2, 3, 4, 5, 6, 7, 8, 9, 1, 0] by tharndt, 11.01.2018 08:17
my code as one liner would be : flat_list = [int(e.replace('[','').replace(']','')) for e in str(deep_list).split(',')] by tharndt, 11.01.2018 08:32
You are indeed right +1, ᴡʜᴀᴄᴋᴀᴍᴀᴅᴏᴏᴅʟᴇ3000's proposal won't work with multiple digit numbers, I also didn't test this before although it should be obvious. You could simplify your code and write [int(e.strip('[ ]')) for e in str(deep_list).split(',')]. But I'd suggest to stick with Deleet's proposal for real use cases. It doesn't contain hacky type transformations, it's faster and more versatile because it naturally also handles lists with mixed types. by Darkonaut, 11.01.2018 16:31
Thanks! This was of course supposed to be funny. I've seen Deleet's proposal in a python book before. by tharndt, 13.01.2018 08:02
Can you tell us which book? I contemplated a lot about this because it's so effective and beautiful. Will hit recursion limit inevitably in general but for cases like this with few recursions it seems perfect. by Darkonaut, 13.01.2018 16:04
Unfortunately no. But I saw this code recently here: Python Practice Book 6.1.2 by tharndt, 15.01.2018 08:18
Show remaining 2 comments
1
5
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
08.08.2017 14:59
Comments
Fails for python2.7 for the example nested list in the question: [[1, 2, 3], [4, 5, 6], [7], [8, 9]] by EL_DON, 22.04.2019 21:34
1
5

This may not be the most efficient way but I thought to put a one-liner (actually a two-liner). Both versions will work on arbitrary hierarchy nested lists, and exploits language features (Python3.5) and recursion.

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

The output is

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

This works in a depth first manner. The recursion goes down until it finds a non-list element, then extends the local variable flist and then rolls back it to the parent. Whenever flist is returned, it is extended to the parent's flist in the list comprehension. Therefore, at the root, a flat list is returned.

The above one creates several local lists and returns them which are used to extend the parent's list. I think the way around for this may be creating a gloabl flist, like below.

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

The output is again

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

Although I am not sure at this time about the efficiency.

16.05.2018 09:41
Comments
Why extend([l]) instead of append(l)? by Maciek, 09.04.2020 18:31
0
5
flat_list = []
for i in list_of_list:
    flat_list+=i

This Code also works fine as it just extend the list all the way. Although it is much similar but only have one for loop. So It have less complexity than adding 2 for loops.

20.06.2018 11:12
0
6

This is a play on the original poster's code. (He wasn't far off)

f = []
list(map(f.extend, l))
10.01.2021 19:27
2
-1

This works with abitrarily nested lists. It can be easily extended to work with other kinds of iterables.

def flatten(seq):
    """list -> list                                                                                                                                                                           
    return a flattend list from an abitrarily nested list                                                                                                                                     
    """
    if not seq:
        return []
    if not isinstance(seq[0], list):
        return [seq[0]] + flatten(seq[1:])
    return flatten(seq[0]) + flatten(seq[1:])

Sample run

>>> flatten([1, [2, 3], [[[4, 5, 6], 7], [[8]]], 9])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
28.11.2018 01:00
Comments
return seq <- No no no no no. Never write a function that sometimes returns a new object and sometimes returns the input object. Always return a new list. by Aran-Fey, 23.10.2019 05:42
@Aran-Fey I see how that may be problematic with functions such as def identity(x): return x in which case it will cause problems when applied to mutable objects passed by reference such as lists because what is returned is essentialy an alias to the original. However in this case, provided the original list passed in is not the empty list, there should be no such problem. I will update it accordingly to address that case. by Xero Smith, 23.10.2019 06:50
0
2

Here is a function using recursion which will work on any arbitrary nested list.

def flatten(nested_lst):
    """ Return a list after transforming the inner lists
        so that it's a 1-D list.

    >>> flatten([[[],["a"],"a"],[["ab"],[],"abc"]])
    ['a', 'a', 'ab', 'abc']
    """
    if not isinstance(nested_lst, list):
        return(nested_lst)

    res = []
    for l in nested_lst:
        if not isinstance(l, list):
            res += [l]
        else:
            res += flatten(l)


    return(res)

>>> flatten([[[],["a"],"a"],[["ab"],[],"abc"]])
['a', 'a', 'ab', 'abc']
11.08.2019 11:00
1
1

A simple recursive method using reduce from functools and the add operator on lists:

>>> from functools import reduce
>>> from operator import add
>>> flatten = lambda lst: [lst] if type(lst) is int else reduce(add, [flatten(ele) for ele in lst])
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

The function flatten takes in lst as parameter. It loops all the elements of lst until reaching integers (can also change int to float, str, etc. for other data types), which are added to the return value of the outermost recursion.

Recursion, unlike methods like for loops and monads, is that it is a general solution not limited by the list depth. For example, a list with depth of 5 can be flattened the same way as l:

>>> l2 = [[3, [1, 2], [[[6], 5], 4, 0], 7, [[8]], [9, 10]]]
>>> flatten(l2)
[3, 1, 2, 6, 5, 4, 0, 7, 8, 9, 10]
20.09.2018 04:55
Comments
@MitchMcMabers That is only because you are having a string in your list, you can modify the function to accept str too by adding or type(lst) is str to the conditions to stop the recursion. by lopezvit, 25.06.2020 11:23
2
0

I recently came across a situation where I had a mix of strings and numeric data in sublists such as

test = ['591212948',
['special', 'assoc', 'of', 'Chicago', 'Jon', 'Doe'],
['Jon'],
['Doe'],
['fl'],
92001,
555555555,
'hello',
['hello2', 'a'],
'b',
['hello33', ['z', 'w'], 'b']]

where methods like flat_list = [item for sublist in test for item in sublist] have not worked. So, I came up with the following solution for 1+ level of sublists

def concatList(data):
    results = []
    for rec in data:
        if type(rec) == list:
            results += rec
            results = concatList(results)
        else:
            results.append(rec)
    return results

And the result

In [38]: concatList(test)
Out[38]:
 Out[60]:
['591212948',
'special',
'assoc',
'of',
'Chicago',
'Jon',
'Doe',
'Jon',
'Doe',
'fl',
92001,
555555555,
'hello',
'hello2',
'a',
'b',
'hello33',
'z',
'w',
'b']
21.09.2017 18:53
Comments
Yup that works but the constant concatenation to a temporary list, and then returning temporary lists, and appending those temporary lists to other temporary lists, of other return-values etc etc, is slow... Should be using Generators instead. by Mitch McMabers, 07.11.2019 06:56
@MitchMcMabers you can provide an edit if you have a better solution. I wasn’t aiming at building something efficient at the time. Just something that would work. If your data has many (~1k+) nested lists, then I think the problem is something else entirely. by Jon, 07.11.2019 18:13
5
0

Throwing my hat in the ring...

B = [ [...], [...], ... ]
A = []
for i in B:
  A.extend(i)
15.04.2019 19:28
Comments
Constantly calling A.extend() to append and rearrange that temporary list is gonna be slow. Also doesn't handle recursion or non-list elements inside the list. Good luck with input: B = [ [1,2,3], 4, [5, 6], "foo" ]... Not gonna work. by Mitch McMabers, 07.11.2019 06:52
@MitchMcMabers that doesn't make sense. Is Python a programming language or a child's toy? appending to a vector is appending to a vector. Or, at least, it should be. You shouldn't be operating in python lists if performance is your issue. by Chris, 07.11.2019 15:29
@MitchMcMabers no regular language incurs an O(n*(l1) + (n-1)*l2 + ... + ln)) performance penalty for an O(number_of_lists) operation. Python does in order to foster semantic simplicity. This answer is semantically simple, therefore it is in the spirit of the language. Like I said: if performance is a requirement, you should not be using python to begin with. by Chris, 07.11.2019 16:01
It's possible to write this with a recursive generator which visits each element exactly once and does not generate any temporary lists. I think such a solution is O(1). by Mitch McMabers, 08.11.2019 12:16
@MitchMcMabers That is not correct. Even if you merely add the pointers to the end of the root list, the solution is at least O(n), where n is the length of the entire list, unless you have a doubly linked list, in which case it is O(m), where m is the number of lists. it may be "possible" using recursion, but why on earth would you want to write such a complex semantic permutation to do something so incredibly simple? In any compiled language, I can write the above more or less equivalently for zero performance impact. The entire point of python is semantic simplicity. by Chris, 08.11.2019 17:58
2
-2

One posibility is to treat the array as a string:

elements = [[180.0, 1, 2, 3], [173.8], [164.2], [156.5], [147.2], [138.2]]
list(map(float, str(elements).replace("[", "").replace("]", "").split(",")))
15.11.2019 11:24
Comments
The result will be a list of strings though. Also, this code may produce wrong result in case if the inner elements are strings containing commas/square brackets. by Georgy, 15.11.2019 11:56
This method is valid for lists of integers or floats. by Shadowtrooper, 15.11.2019 11:58
0
2

A funny solution 😊

import pandas as pd
list(pd.DataFrame({'lists':l})['lists'].explode())


[1, 2, 3, 4, 5, 6, 7, 8, 9]
02.12.2020 10:22
0
0

This can be done using toolz.concat or cytoolz.concat (cythonized version, that could be faster in some cases):

from cytoolz import concat
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(concat(l)) # or just `concat(l)` if one only wants to iterate over the items

On my computer, in python 3.6, this seems to time almost as fast as [item for sublist in l for item in sublist] (not counting the import time):

In [611]: %timeit L = [item for sublist in l for item in sublist]
695 ns ± 2.75 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [612]: %timeit L = [item for sublist in l for item in sublist]
701 ns ± 5.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [613]: %timeit L = list(concat(l))
719 ns ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [614]: %timeit L = list(concat(l))
719 ns ± 22.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

The toolz version is indeed slower:

In [618]: from toolz import concat

In [619]: %timeit L = list(concat(l))
845 ns ± 29 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [620]: %timeit L = list(concat(l))
833 ns ± 8.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
31.01.2018 09:52
0
1

There are several answers with the same recursive appending scheme as below, but none makes use of try, which makes the solution more robust and pythonic. Other advantages of this solution are:

  • works with any kind of iterable (even future ones)
  • works with any combination and deepness of nesting
  • no dependencies

~

def flatten(itr):
    t = tuple()
    for e in itr:
        try:
            t += flatten(e)
        except:
            t += (e,)
    return t

Another variant with same features:

def flatten(itr):
    try:
        t = sum((flatten(e) for e in itr), tuple())
    except:
        t = (itr,)
    return t

If you need to return a list (which is slightly slower) use list() instead of tuple() and [ ] instead of ( ,).

08.08.2020 14:52
0
1

To loop over a list of list and retreive a flat one, the best solution is to iterate with recursion:

def flat_list_recursion_example(input_list, final_list = []):

    """    
    Retreives a flattend list from a nested one
        Args:
            input_list(list): nested list of list. Example [[0,1],[2],[3,4]]
            final_list(list): final structure. By default []

        Returns:
            flattened list: Example [0,1,2,3,4]
    """

    if not input_list:
        return final_list

    final_list.extend(input_list[0])

    return flat_list_recursion_example(input_list[1:],final_list)

You can use this with the following example:

l_0 = [i for i in range(1, 660001)]
l_1 = [i for i in range(1, 660001)]
l_2 = [i for i in range(1, 660001)]
l = [l_0,l_1,l_2]

flat_list = flat_list_recursion_example(l,[])
print(len(flat_list))

I´ve checked in a Jupyter notebook with many solutions proposed in this thread, and this is the fastest one, at least measuring the times with %timeit

enter image description here

12.05.2021 12:27
2
0

There is another method for doing this:

l=[[1,2,3],[4,5,6],[7,8,9]]
from functools import reduce
k=reduce(lambda l1,l2:l1+l2,l)
print(k)
20.04.2021 14:24
Comments
Code only answers are discouraged. Please provide a summary of how your answer solves the problem and why it may be preferable to the other answers provided. by DaveL17, 20.04.2021 23:02
Welcome to Stack Overflow. Code dumps without any explanation are rarely helpful. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please edit your question and explain how it answers the specific question being asked. See How to Answer. This is particularly important when answering old questions (this one is nearly 12 years old) with existing answers (there are already 84 answers here). How does this improve upon what's already here? by Chris, 21.04.2021 00:06
2
1

The solution should not considers that there is only one or two nesting levels. The level of nesting should be considered as one variable of the problem. I suggest the following solution

a=[1,[2,3],[4,[[[5]]],6],7,[8,9,10,11,12],[13,14,[15,16,17,[18,19,20,21,22],23,24],25],26,[27,28,29],30]
print(a)
temp=a
flat_list=[]
check=True
while check==True:
    minor_check=False    # check for at least one nesting order: initial guess
    for i in range(len(temp)):
        if (isinstance(temp[i],list)):
            minor_check=True  # there is at least one nesting order deeper in the list
            for ii in range(len(temp[i])):
                flat_list.append(temp[i][ii])
        else:
            flat_list.append(temp[i])
    check=True if minor_check==True else False
    temp=flat_list
    print(temp) # print the new flat_list at after this pass
    flat_list=[]

flat_list=temp
print(flat_list)
    

I hope that this will help

18.03.2021 15:15
Comments
Problem with answers to questions like this is that probably nobody will ever reach the 3 page :) by dreamcrash, 21.03.2021 14:38
@dreamcrash This is exactly what I'm noticing by Noureddine, 21.03.2021 14:55
0
0

I would like to use the concatenate and ravel of the numpy as below

import numpy as np
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]

out = np.concatenate(np.array(l)).ravel()
31.01.2021 05:35
2
0

In python 3 we do this by using + operator

l=[1,2,3]
m=[4,5,6]
n=[7,8,9]

print(l+m+n)

This gives the final list having all the elements

20.04.2021 14:20
Comments
Welcome to Stack Overflow. Code dumps without any explanation are rarely helpful. Stack Overflow is about learning, not providing snippets to blindly copy and paste. Please edit your question and explain how it answers the specific question being asked. See How to Answer. This is particularly important when answering old questions (this one is nearly 12 years old) with existing answers (there are already 84 other answers). How does this answer improve upon what's already here? by Chris, 21.04.2021 00:12
OP wants to flatten nested lists, this is unrelated by Adam, 28.04.2021 19:47
1
-2
np.hstack(listoflist).tolist()
06.11.2020 17:04
Comments
While this code may answer the question, providing additional context regarding why and/or how this code answers the question improves its long-term value. Consider reading How to Answer and edit your answer to improve it. by Donald Duck, 06.11.2020 19:31
0
0

Shorter version of Arty's answer for infinite depth-lists and other iterable objects

from collections.abc import Iterable
def flatten(x):
    if isinstance(x, Iterable):
        return sum([flatten(i) for i in x], [])
    return [x]

flatten( [[3, 4], [[5, 6], 6]])
# output [3, 4, 5, 6, 6]
29.04.2021 11:21