aplatir liste de liste de liste de compréhension

j'essaie d'aplatir une liste en utilisant la compréhension de liste en python. Ma liste est un peu comme

[[1, 2, 3], [4, 5, 6], 7, 8]

juste pour l'impression, puis l'élément individuel dans cette liste de liste j'ai écrit ce 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

Ensuite, j'ai utilisé la même logique pour aplatir ma liste liste de compréhension, j'obtiens l'erreur suivante

    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

Comment puis-je aplatir ce type de liste en utilisant la compréhension de liste ?

10
demandé sur Ashwini Chaudhary 2013-06-27 13:01:25

5 réponses

>>> 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]

Une version lisible:

>>> 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']

en utilisant la compréhension de liste imbriquée: (va être lent comparé à 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']
7
répondu Ashwini Chaudhary 2013-06-27 09:21:04

personne N'a donné la réponse habituelle:

def flat(l):
  return [y for x in l for y in x]

il y a des doubles de cette question qui flottent autour de StackOverflow.

5
répondu GreenAsJade 2014-01-02 09:33:31

une solution alternative utilisant un générateur:

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]
3
répondu Gareth Latty 2013-06-27 09:18:40

vous essayez d'itérer un nombre, ce que vous ne pouvez pas faire (d'où l'erreur).

si vous utilisez python 2.7:

>>> from compiler.ast import flatten
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8]

mais notez que le module est maintenant déprécié, et n'existe plus en Python 3

3
répondu TerryA 2013-06-27 09:18:41
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]
1
répondu Alessandro Anderson 2018-08-25 09:53:14