2014-11-12 23 views
15

La funzione accetta un elenco e restituisce un secondo in base a quanti elenchi sono presenti nell'elenco senza includere l'elenco stesso. (Per semplicità possiamo assumere tutto è un numero intero o un elenco.)Come trovare il numero di elenchi annidati in un elenco?

Ad esempio:

x=[1,2,[[[]]],[[]],3,4,[1,2,3,4,[[]] ] ] 

count_list(x) # would return 8 

Credo che utilizzando la ricorsione avrebbe aiutato, ma non sono sicuro come implementarlo, questo è quello che ho finora.

def count_list(a,count=None, i=None): 

    if count==None and i==None: 
     count=0 
     i=0 
    if i>len(a) 
     return(count) 
    if a[i]==list 
     i+=1 
     count+=1 
     return(count_list(a[i][i],count)) 
    else: 
     i+=1 
     return(count_list(a[i])) 
+6

Che ne dite di una risposta, ovviamente, non va? 'str (x) .count (" [") - 1' –

+1

fintanto che non ci sono stringhe in nessuna lista, quella soluzione è PROBABILE non peggiore della ricorsione. Se ci sono stringhe in una lista allora potresti avere una stringa che contiene '" ["' che rompe tutto di sempre. –

+1

Sulla riga 'def', ci dovrebbero essere singoli segni di uguale non doppio. –

risposta

17

Questo sembra fare il lavoro:

def count_list(l): 
    count = 0 
    for e in l: 
     if isinstance(e, list): 
      count = count + 1 + count_list(e) 
    return count 
+3

Beh, dal punto di vista di qualcuno che non conosce Python, penso che il tuo sia più leggibile, anche se ovviamente fanno la stessa cosa. Per i programmatori principianti, la leggibilità supera bruscamente una riga o due secondo me;) –

21

si può fare con una funzione di ricorsione:

def count(l): 
    return sum(1+count(i) for i in l if isinstance(i,list)) 

Demo:

>>> x=[1,2,[[[]]],[[]],3,4,[1,2,3,4,[[]] ] ] 
>>> count(x) 
8 
+2

+1 per il modo "pythonic" per risolvere questo – oopbase

3

Una soluzione in stile funzionale senza loop. Elabora in modo ricorsivo il primo elemento di un elenco e la coda di un elenco. Aggiungine uno per ogni lista vuota incontrata (cioè, una volta che abbiamo finito di elaborare qualche lista, la sua coda diventa vuota, e aggiungiamo 1 al risultato). E sottrarre 1 per la lista stessa.

def number_of_lists(x): 
    f = lambda x: 0 if not isinstance(x,list) else (f(x[0]) + f(x[1:]) if len(x) else 1) 
    return f(x) - 1 

Risultati:

x=[1,2,[[[]]],[[]],3,4,[1,2,3,4,[[]] ] ] 
number_of_lists(x) 
>> 8 
5

Ecco una soluzione non ricorsiva:

  1. primo luogo, mettere ogni elementi della lista in una pila
  2. continuano a spuntare una voce fuori dal accumulare fino all'esaurimento
  3. Se l'articolo è un elenco: a) contarlo, b) inserire tutti gli elementi nello sta ck

Il codice:

def count_list(lst): 
    """ Given a master list, count the number of sub-lists """ 
    stack = lst[:] 
    count = 0 
    while stack: 
     item = stack.pop() 
     if isinstance(item, list): 
      # If the item is a list, count it, and push back into the 
      # stack so we can process it later 
      count += 1 
      stack.extend(item) 
    return count 
3

Mi piace questa soluzione ricorsiva di coda, anche se non è molto uso in Python ...

def count_lists(l, counter): 
    if (len(l) == 0): 
     return counter 
    else: 
     e = l.pop(0) 
     if (isinstance(e, list)): 
      l.extend(e) 
      return count_lists(l, 1 + counter) 
     else: 
      return count_lists(l, counter) 

x=[1,2,[[[]]],[[]],3,4,[1,2,3,4,[[]]]] 
print(count_lists(x, 0)) 
+0

concordato. Bummer :( – ojy

+0

Non sono all'altezza degli algoritmi - c'è una ragione per cui stai facendo 'l.pop (0)' invece di 'l.pop()'? Se funzionasse anche, modo, il secondo è MASSIVAMENTE più veloce: –

+0

Sì, c'è una differenza tra i due. 'Pop (0)' rimuove il primo elemento dall'elenco mentre 'pop() 'rimuove l'ultimo.Un buon punto sulle prestazioni, l'algoritmo può essere modificato per usare il pop () anziché. – benji

Problemi correlati