2017-08-04 2 views
0

Ich habe ein kleines Problem, bei dem mir einiges an Python-Erfahrung fehlt. Unter der Annahme einer Liste:Teilliste Abflachung in Python

list=[[40, 20, 45, 40], [[20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]] 

ich etwas, das ich ‚teilweise Abflachung‘ nennen wollen, weil die erwartete Ausgabe ist:

[[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]] 

Nachricht vor der lentgh von list war 2, während die erwartete Ausgabe Länge von 3. Das Problem ist, dass ich nicht im Voraus weiß, welches Element von list eine Schicht tiefer verschachtelt ist.

This answer und viele andere half nicht viel, weil die Abflachung zu weit geht. Im Anschluss an die Frage der Ausgabe lautet:

list=[40, 20, 45, 40, [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]] 

(die fehlenden Klammern für die ersten 4 Elemente aus der Liste merken

+2

So möchten Sie eine Liste aller inner meisten Listen? Kann es eine Eingabeliste wie '[1,2, [3,4]]' geben, und wenn ja, wie sollte diese abgeflacht werden? –

+0

@tobias_k Eine solche Eingabeliste ist nicht möglich. – skrat

+1

Sie sagen uns, was die Ausgabe für dieses spezielle Beispiel ist, und ich verstehe das. Aber worauf basiert diese Entscheidung? Was ist die Regel darauf, was geglättet werden sollte? Es ist völlig unklar, wie die Logik sein soll? Und wenn Sie einmal da sind, welches Problem haben Sie, es selbst zu lösen, wenn Sie bereits andere Glättungsmethoden gesehen und angewendet haben? – poke

Antwort

1

Sie können eine rekursive Funktion erstellen, testen, ob all die inneren Elemente sind Listen Wenn ja.. , den Algorithmus rekursiv anzuwenden, da sonst die Liste ergeben sich

def inner_lists(lst): 
    if all(isinstance(x, list) for x in lst): 
     for inner in lst: 
      for x in inner_lists(inner): 
       yield x 
    else: 
     yield lst 

>>> lst = [[40, 20, 45, 40], [[20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]] 
>>> list(inner_lists(lst)) 
[[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]] 

Or yield from (Python 3.3 und höher).

def inner_lists(lst): 
    if all(isinstance(x, list) for x in lst): 
     yield from (x for inner in lst for x in inner_lists(inner)) 
    else: 
     yield lst 

oder ohne Generatoren:

def inner_lists(lst): 
    if all(isinstance(x, list) for x in lst): 
     return [x for inner in lst for x in inner_lists(inner)] 
    else: 
     return [lst] 
+2

In Python 3 können Sie' yield von inneren_listen (innen) 'verwenden –

1

Wenn Ihre Listen können nur Zahlen enthält oder Teillisten (nicht von ihnen beide) Sie verwenden können Generatorfunktion folgende:

In [25]: def partial_flattening(lst): 
      for sub in lst: 
       if isinstance(sub[0], list): 
        yield from sub # in python 2.x use for i in sub: yeild i 
       else:   
        yield sub 
    ....:     

In [26]: list(partial_flattening(lst)) 
Out[36]: [[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]] 

Wenn Kombination sein kann von beiden Arten dann basierend auf, was Sie mit den Zahlen tun möchten, können Sie die Funktion anpassen.

Oder als prägnanter Ansatz, den Sie yield innerhalb Liste Verständnis verwenden können:

In [29]: list([(yield from i) if isinstance(i[0], list) else (yield i) for i in lst]) 
Out[29]: [[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]] 
+0

Wusste nicht, dass Sie 'yield' in einer Liste comp verwenden könnten. Beide funktionieren jedoch nur für eine einzelne Verschachtelungsebene (was bei OPs Beispiel völlig in Ordnung sein könnte). –

Verwandte Themen