flatten list of list through list comprehension

10,441

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]
Share:
10,441
Anurag Sharma
Author by

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, 2022

Comments

  • Anurag Sharma
    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
    Gareth Latty almost 11 years
    This is great for the asker using 2.x, but it's worth a note that 3.x users should use str instead of basestring.
  • Gareth Latty
    Gareth Latty almost 11 years
    Type checking lists is a bad idea. It makes this much less flexible.
  • falsetru
    falsetru almost 11 years
    if 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
    TerryA almost 11 years
    Removed the first bit, but it's a shame that my other solution won't work in python 3
  • Anurag Sharma
    Anurag Sharma almost 11 years
    @Ashwini What should be done if my elements are of type dict instead of integer?
  • Ashwini Chaudhary
    Ashwini Chaudhary almost 11 years
    @AnuragSharma small example?
  • Anurag Sharma
    Anurag Sharma almost 11 years
    @AshwiniChaudhary for example ---> [[{'ascdd': 'skj'}, {'fd': 'srsr'}], {'dsf': 'ds', 'ds': 'dsffd'}]
  • Ashwini Chaudhary
    Ashwini Chaudhary almost 11 years
    @AnuragSharma what is the expected output for this case?
  • Anurag Sharma
    Anurag Sharma almost 11 years
    @AshwiniChaudhary expected output ---> [{'ascdd': 'skj'}, {'fd': 'srsr'},{'dsf': 'ds', 'ds': 'dsffd'}] or simply a list of dictionary
  • JDG
    JDG almost 9 years
    Your 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
    GreenAsJade almost 9 years
    Thanks for pointing that out - I'll actually need to find a moment to mess around with that and come to grips...
  • scopchanov
    scopchanov over 5 years
    Probably an explanation would be helpful as well.
  • Alessandro Anderson
    Alessandro Anderson over 5 years
    This 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
    scopchanov over 5 years
    Great! Now please edit your answer adding this information.
  • Alessandro Anderson
    Alessandro Anderson over 5 years
    Done - Namasté.
  • Nishant
    Nishant about 2 years
    Double 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].