flatten list of list through list comprehension
Solution 1
>>> from collections import Iterable
>>> from itertools import chain
One-liner:
>>> list(chain.from_iterable(item if isinstance(item,Iterable) and
not isinstance(item, basestring) else [item] for item in lis))
[1, 2, 3, 4, 5, 6, 7, 8]
A readable version:
>>> def func(x): #use `str` in py3.x
... if isinstance(x, Iterable) and not isinstance(x, basestring):
... return x
... return [x]
...
>>> list(chain.from_iterable(func(x) for x in lis))
[1, 2, 3, 4, 5, 6, 7, 8]
#works for strings as well
>>> lis = [[1, 2, 3], [4, 5, 6], 7, 8, "foobar"]
>>> list(chain.from_iterable(func(x) for x in lis))
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']
Using nested list comprehension:(Going to be slow compared to itertools.chain
):
>>> [ele for item in (func(x) for x in lis) for ele in item]
[1, 2, 3, 4, 5, 6, 7, 8, 'foobar']
Solution 2
No-one has given the usual answer:
def flat(l):
return [y for x in l for y in x]
There are dupes of this question floating around StackOverflow.
Solution 3
You're trying to iterate through a number, which you can't do (hence the error).
If you're using python 2.7:
>>> from compiler.ast import flatten
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8]
But do note that the module is now deprecated, and no longer exists in Python 3
Solution 4
An alternative solution using a generator:
import collections
def flatten(iterable):
for item in iterable:
if isinstance(item, collections.Iterable) and not isinstance(item, str): # `basestring` < 3.x
yield from item # `for subitem in item: yield item` < 3.3
else:
yield item
>>> list(flatten([[1, 2, 3], [4, 5, 6], 7, 8]))
[1, 2, 3, 4, 5, 6, 7, 8]
Solution 5
def nnl(nl): # non nested list
nn = []
for x in nl:
if type(x) == type(5):
nn.append(x)
if type(x) == type([]):
n = nnl(x)
for y in n:
nn.append(y)
return nn
print (nnl([[9, 4, 5], [3, 8,[5]], 6])) # output: [9, 4, 5, 3, 8, 5, 6]
Anurag Sharma
I have completed my Masters from University of Florida and currently working as a Python Developer. I enjoy learning and working on problems pertaining to the domains of Data Analytics, Sentiment Analysis and Information Retrieval.
Updated on June 03, 2022Comments
-
Anurag Sharma almost 2 years
I am trying to flatten a list using list comprehension in python. My list is somewhat like
[[1, 2, 3], [4, 5, 6], 7, 8]
just for printing then individual item in this list of list I wrote this code
def flat(listoflist): for item in listoflist: if type(item) != list: print item else: for num in item: print num >>> flat(list1) 1 2 3 4 5 6 7 8
Then I used the same logic to flatten my list through list comprehension I am getting the following error
list2 = [item if type(item) != list else num for num in item for item in list1] Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'int' object is not iterable
How can I flatten this type of list-of-list using using list comprehension ?
-
Gareth Latty almost 11 yearsThis is great for the asker using 2.x, but it's worth a note that 3.x users should use
str
instead ofbasestring
. -
Gareth Latty almost 11 yearsType checking lists is a bad idea. It makes this much less flexible.
-
falsetru almost 11 yearsif
l
is[[1, 2, 3], [4, 5, 6], 7, 888]
, the first solution yields[1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
. -
TerryA almost 11 yearsRemoved the first bit, but it's a shame that my other solution won't work in python 3
-
Anurag Sharma almost 11 years@Ashwini What should be done if my elements are of type dict instead of integer?
-
Ashwini Chaudhary almost 11 years@AnuragSharma small example?
-
Anurag Sharma almost 11 years@AshwiniChaudhary for example ---> [[{'ascdd': 'skj'}, {'fd': 'srsr'}], {'dsf': 'ds', 'ds': 'dsffd'}]
-
Ashwini Chaudhary almost 11 years@AnuragSharma what is the expected output for this case?
-
Anurag Sharma almost 11 years@AshwiniChaudhary expected output ---> [{'ascdd': 'skj'}, {'fd': 'srsr'},{'dsf': 'ds', 'ds': 'dsffd'}] or simply a list of dictionary
-
JDG almost 9 yearsYour code does not work for the list the OP provided because his list includes non-iterable objects, namely integers. Your code does however work if every item in the list is an iterable object. See my comment below.
-
GreenAsJade almost 9 yearsThanks for pointing that out - I'll actually need to find a moment to mess around with that and come to grips...
-
scopchanov over 5 yearsProbably an explanation would be helpful as well.
-
Alessandro Anderson over 5 yearsThis solution uses recursion. For every element in the nested list you check if the element is an integer or a list. If an integer, we append that integer in the list nn. If the element in the nested list is a list, call a recursive function, you will do to the sublist what you did to the initial nested list. Then append the elements that are not a list again in nn. The output of nn will be a non nested list. Happy coding everybody!
-
scopchanov over 5 yearsGreat! Now please edit your answer adding this information.
-
Alessandro Anderson over 5 yearsDone - Namasté.
-
Nishant about 2 yearsDouble
for
is interesting. The above problem can also be solved using:[z for y in [x if isinstance(x, list) else [x] for x in [1, [2]]] for z in y]
.