2013-10-21 12 views
22

nur mit Python Herumspielen begann so bitte Geduld mit mir :)Python - Extrahierung des inneren meisten Listen

Nehmen Sie die folgende Liste, die verschachtelte Listen enthält:

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

In einer anderen Darstellung:

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

Wie würden Sie diese inneren Listen extrahieren, so dass ein Ergebnis mit dem folgenden Formular zurückgegeben würde:

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

Vielen Dank!

EDIT (Danke @falsetru):

Leere innere Liste oder gemischte Listen werden nie Teil der Eingabe sein.

+2

Was für zurückgegeben werden sollte '[[[[[1, 3, 4, 5]], [1, 3, 8]] , [[1, 7, 8]]], [[[6, 7, 8]]], [9, [10]]] und "[[[[[1, 3, 4, 5]]", [1, 3, 8]], [[1, 7, 8]]], [[[6, 7, 8]]]], []] '? – falsetru

+0

Danke für die klärende Frage: Eine leere Liste oder eine Liste mit gemischten Art von Elementen wird nie Teil der Eingabe sein –

Antwort

32

Dies scheint zu funktionieren, sofern keine 'gemischten' Listen wie [1,2,[3]]:

def get_inner(nested): 
    if all(type(x) == list for x in nested): 
     for x in nested: 
      for y in get_inner(x): 
       yield y 
    else: 
     yield nested 

Ausgabe von list(get_inner(nested_list)):

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

Oder noch kürzer, ohne Generatoren, mit sum die resultierenden Listen kombinieren :

def get_inner(nested): 
    if all(type(x) == list for x in nested): 
     return sum(map(get_inner, nested), []) 
    return [nested] 
+0

Schön! Danke :) –

13

Verwenden itertools.chain.from_iterable:

from itertools import chain 

def get_inner_lists(xs): 
    if isinstance(xs[0], list): # OR all(isinstance(x, list) for x in xs) 
     return chain.from_iterable(map(get_inner_lists, xs)) 
    return xs, 

verwendet isinstance(xs[0], list) statt all(isinstance(x, list) for x in xs), weil es keine gemischte Liste/leeren Innen Liste ist.


>>> list(get_inner_lists([[[[[1, 3, 4, 5]], [1, 3, 8]], [[1, 7, 8]]], [[[6, 7, 8]]], [9]])) 
[[1, 3, 4, 5], [1, 3, 8], [1, 7, 8], [6, 7, 8], [9]] 
5

Effizienter als Rekursion:

result = [] 
while lst: 
    l = lst.pop(0) 
    if type(l[0]) == list: 
     lst += [sublst for sublst in l if sublst] # skip empty lists [] 
    else: 
     result.insert(0, l) 
+3

Das erste Element aus der Liste löschen, Einfügen in den Anfang der Liste nehmen Sie O (n) Zeit. Die Verwendung von ['collections.deque'] (http://docs.python.org/2/library/collections.html#collections.deque) könnte die Geschwindigkeit verbessern. Siehe http://ideone.com/RFGhnh – falsetru

+1

Wenn Sie behaupten, dass Ihre Lösung effizienter ist als andere Lösungen, fügen Sie bitte Benchmarks für kleine und große Eingaben bei. Siehe faltru's Kommentar, warum es langsam ist. – pts