2

I have a nested list mixed with list and numbers.

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

The nested lists only contain numbers, they'll never contain more lists.

Is it possible to write a list comprehension to make new list from the 'nested' list, producing the following output?

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

This was my attempt( code is not working)

[num if isinstance(item, list) for num in item else item for item in nested]
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
Fuji Komalan
  • 1,979
  • 16
  • 25

2 Answers2

7

You need to put your instance test in a loop, so you can extract the elements from a nested list:

[num for item in nested for num in (item if isinstance(item, list) else (item,))]

Demo:

>>> nested = nested = [[1, 2, 3], [4, 5, 6], [7, 8], [9], 10, 11]
>>> [num for item in nested for num in (item if isinstance(item, list) else (item,))]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

It helps if you first express this as a set of for loops; your attempt essentially did this:

for item in nested:
    _element = num if isinstance(item, list) for num in item else item
    result.append(_element)

which is not really valid Python.

My list comprehension above instead does this:

for item in nested:
    _iterable = item if isinstance(item, list) else (item,)
    for num in _iterable:
        _element = num
        result.append(_element)
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Great answer, It does not account for a list containing tuples or a iterable containers and non iterable objects as a usage note... – dawg Jun 07 '17 at 18:38
  • @dawg: no, because that's outside the requirements of the question, it's why I asked for the clarifications on the post and ultimately duped this to a different post from the one I link to in the comments. – Martijn Pieters Jun 07 '17 at 21:38
1

If your list has arbitrary nesting, best to use a recursive function (referring to one of my other answers):

>>> def flat_gen(x):
...     def iselement(e):
...         return not(isinstance(e, collections.Iterable) and not isinstance(e, str))
...     for el in x:
...         if iselement(el):
...             yield el
...         else:
...             yield from flat_gen(el)   
... 
>>> nested = [[1,2,3] , [4,5,6] , [7,8] , [9,] , 10 , 11 ]

>>> import collections
>>> list(flat_gen(nested))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

If you just have mixed nesting between a simple list or tuple (any iterable container) and non list or tuple objects (i.e., non-iterable objects and iterable containers with no deeper nesting) you can use a generator expression with list:

>>> import itertools as it
>>> list(it.chain.from_iterable(item if isinstance(item,collections.Iterable) and not isinstance(item, str) else [item] for item in nested))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
dawg
  • 98,345
  • 23
  • 131
  • 206
  • 1
    The OP asked for a list comprehension, otherwise we could just as much have duped to the question you based this on. – Martijn Pieters Jun 07 '17 at 15:55
  • 1
    @MartijnPieters It's a clear dupe anyway, no? https://stackoverflow.com/questions/17338913/flatten-list-of-list-through-list-comprehension – Stefan Pochmann Jun 07 '17 at 16:33
  • @StefanPochmann: interesting, had not seen that one. And there is no correct list comprehension answer there. – Martijn Pieters Jun 07 '17 at 16:35
  • @StefanPochmann: I believe that one allows for more nesting though. – Martijn Pieters Jun 07 '17 at 16:36
  • @MartijnPieters I don't think so. The question contains printing code which can't handle deeper nesting and the question makes it sound like that's working. – Stefan Pochmann Jun 07 '17 at 16:38
  • @StefanPochmann: ah, I actually missed that Ashwini includes a list comp version (but made matters more complicated by using a separate function to wrap single elements in a sequence and a nested generator expression). – Martijn Pieters Jun 07 '17 at 16:41
  • @MartijnPieters And the accepted answer doesn't do deeper nesting, either, and still got accepted. But yeah, odd that none of the seven answers there does a list comprehension like yours. – Stefan Pochmann Jun 07 '17 at 16:41