Een ondiepe lijst afvlakken in Python

| | | | | | | | | | | | | |

Is er een eenvoudige manier om een lijst met iterables af te vlakken met een lijstbegrip, of als dat niet lukt, wat zouden jullie allemaal beschouwen als de beste manier om een ondiepe lijst als deze af te vlakken, waarbij prestaties en leesbaarheid in evenwicht zijn?

Ik heb geprobeerd zo'n lijst af te vlakken met een geneste lijstbegrip, zoals dit:

[afbeelding voor afbeelding in menuitem voor menuitem in list_of_menuitems] 

Maar ik krijg daar problemen met de NameError variant, omdat de naam "menuitem" niet gedefinieerd is. Na googlen en rondkijken op Stack Overflow, kreeg ik de gewenste resultaten met een reduce-instructie:

reduce(list.__add__, map(lambda x: list(x ), list_of_menuitems)) 

Maar deze methode is redelijk onleesbaar omdat ik die list(x)-aanroep daar nodig heb omdat x een Django QuerySet object.

Conclusie:

Bedankt aan iedereen die heeft bijgedragen aan deze vraag. Hier is een samenvatting van wat ik heb geleerd. Ik maak er ook een community-wiki van voor het geval anderen deze observaties willen aanvullen of corrigeren.

Mijn oorspronkelijke reduce-statement is overbodig en kan beter op deze manier worden geschreven:

>>> reduce(list.__add__, (list(mi) for mi in list_of_menuitems)) 

Dit is de juiste syntaxis voor een geneste lijstbegrip (Briljante samenvatting dF!):

>>> [afbeelding voor mi in list_of_menuitems voor afbeelding in mi] 

Maar geen van deze methoden is zo efficiënt als het gebruik van itertools.chain:

>>> ; from itertools import chain >>> list(chain(*list_of_menuitems)) 

En zoals @cdleary opmerkt, is het waarschijnlijk een betere stijl om * operator-magie te vermijden door chain.from_iterable zoals:

>>> chain = itertools.chain.from_iterable([[1,2],[3],[5,89],[],[6]]) >>> print(lijst(keten)) >>> [1, 2, 3, 5, 89, 6]