2013-10-21 11 views
22

appena iniziato giocando in giro con Python quindi per favore portare con me :)Python - L'estrazione di interni maggior parte delle liste

Assumere il seguente elenco, che contiene elenchi annidati:

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

In una diversa rappresentazione:

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

Come procederesti all'estrazione di quelle liste interne in modo da restituire un risultato con il seguente modulo:

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

Grazie mille!

EDIT (Grazie @falsetru):

vuoti interno-list o di tipo misto liste non sarà mai parte dell'ingresso.

+2

Quale dovrebbe essere restituito per '[[[[[1, 3, 4, 5]], [1, 3, 8]] , [[1, 7, 8]]], [[[6, 7, 8]]], [9, [10]]] e '[[[[[1, 3, 4, 5]], [1, 3, 8]], [[1, 7, 8]]], [[[6, 7, 8]]], []] '? – falsetru

+0

Grazie per la domanda di chiarimento: Un elenco vuoto o un elenco con tipi misti di elementi non saranno mai parte dell'input –

risposta

32

Questo sembra funzionare, assumendo l'assenza di liste di 'miste' come [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 

uscita di list(get_inner(nested_list)):

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

O anche più breve, senza generatori, utilizzando sum di combinare le liste risultanti :

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

Beautiful! Grazie :) –

13

Utilizzo 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, 

utilizzato isinstance(xs[0], list) anziché all(isinstance(x, list) for x in xs), perché non c'è lista mista/vuoto lista interna.


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

Più efficiente di ricorsione:

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

Eliminazione del primo elemento dall'elenco, Inserimento all'inizio della lista richiede O (n) tempo. L'utilizzo di ['collections.deque'] (http://docs.python.org/2/library/collections.html#collections.deque) potrebbe migliorare la velocità. Vedere http://ideone.com/RFGhnh – falsetru

+1

Se si sostiene che la soluzione è più efficiente di altre soluzioni, si prega di allegare benchmark per input piccoli e grandi. Vedi il commento di falsetru perché è lento. – pts

Problemi correlati