2

I want to flatten a list of lists and items. The below code works only for a list of lists

def flatten(li):
return [item for sublist in li for item in sublist]

It would work on

[[1],[2,3],[4]]

but not

[[1],[2,3],[4],5]

I want a function that would do it for the above list - something like

[item if isinstance(sublist, list) else sublist for sublist in li
for item in sublist]

The above code gives an error.

Trying it on

[[1],[2,3],[4],5]

gives me

TypeError: 'int' object is not iterable

Can anyone give me a list comprehension which doesn't?

EDIT:

I want a LIST COMPREHENSION only.

Nikhil Prabhu
  • 1,072
  • 3
  • 12
  • 24
  • How many variants of your list comprehension did you try? Does it have to be a list comprehension? - Sometimes it is easier to *see* the process if you just write out the steps - then you could turn it into a generator function, or work backword to compose the list comprehension. – wwii Aug 11 '16 at 15:21
  • why you want list comprehension so much? making a function that do this will be much better and more readable. Like in the answer to this:[flatten-an-irregular-list-of-lists-in-python](http://stackoverflow.com/questions/2158395/flatten-an-irregular-list-of-lists-in-python) – Copperfield Aug 11 '16 at 20:24
  • I want to see if it is possible to do so with a list comprehension- whether it is only my lack of knowledge and skill prevented me from doing so - or whether it is actually impossible -- and why. This will enrich my knowledge of the language. It's not about the result. – Nikhil Prabhu Aug 12 '16 at 16:06

3 Answers3

1
from itertools import chain

def flatten(li):
    if isinstance(li, list):
        li = [flatten(x) for x in li]
        return list(chain(*li))
    else:
        return [li]

def flatten2(li):
    return list(chain(*[[x] if not isinstance(x, list) else flatten2(x) for x in li]))

it even work on:

[[1], [[2, 3], 4], [5], 6] -> [1, 2, 3, 4, 5, 6]

Else:

def flatten3(li):
    return [x for inner in [[item] if not isinstance(item, list) else item for item in li]  for x in inner]
Cabu
  • 514
  • 2
  • 5
  • 15
1
def flatten(li):

return [ x for x in li if isinstance(x,int) ] + [item for sublist in li if isinstance(sublist,list) for item in sublist]
Soufian
  • 99
  • 5
1

As other users have suggested, using a recursive function to flatten the list works really well in this case. But here is a one line list comprehension (albeit not the most efficient).

from collections import Iterable
l = [{},2,[41,123,'str'],32,(4324),3,1,(212,3213),[2]]
print [num for subitem in (subquery if isinstance(subquery, Iterable) else [subquery] for subquery in l) for num in subitem]
>>> [2, 41, 123, 'str', 32, 4324, 3, 1, 212, 3213, 2]
ospahiu
  • 3,465
  • 2
  • 13
  • 24