Esiste un modo pitonico per scompattare una lista nel primo elemento e la "coda" in un singolo comando?
Per esempio:
>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Esiste un modo pitonico per scompattare una lista nel primo elemento e la "coda" in un singolo comando?
Per esempio:
>> head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Risposte:
In Python 3.x, puoi farlo bene:
>>> head, *tail = [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
Una nuova funzionalità in 3.x consiste nell'utilizzare l' *
operatore durante il disimballaggio, per indicare eventuali valori aggiuntivi. È descritto in PEP 3132 - Extended Iterable Unpacking . Questo ha anche il vantaggio di lavorare su qualsiasi iterabile, non solo su sequenze.
È anche molto leggibile.
Come descritto nel PEP, se vuoi fare l'equivalente in 2.x (senza potenzialmente creare un elenco temporaneo), devi farlo:
it = iter(iterable)
head, tail = next(it), list(it)
Come notato nei commenti, questo fornisce anche l'opportunità di ottenere un valore predefinito per head
invece di generare un'eccezione. Se vuoi questo comportamento, next()
accetta un secondo argomento opzionale con un valore predefinito, quindi next(it, None)
ti darebbe None
se non ci fosse un elemento head.
Naturalmente, se stai lavorando su un elenco, il modo più semplice senza la sintassi 3.x è:
head, tail = seq[0], seq[1:]
__getitem__
/ __setitem__
per eseguire pigramente l'operazione tail, ma l'elenco predefinito non lo fa.
python 3.x
Tuttavia, per la complessità head,tail
operativa O (1) è necessario utilizzare deque
.
Modo seguente:
from collections import deque
l = deque([1,2,3,4,5,6,7,8,9])
head, tail = l.popleft(), l
È utile quando è necessario scorrere tutti gli elementi dell'elenco. Ad esempio in ingenuo unire 2 partizioni in merge sort.
head, tail = l.popleft(), l
è ~ O (1). head, tail = seq[0], seq[1:]
è O (n).
head = l.popleft()
ed tail
è solo un alias per l
. Se l
cambia tail
cambia troppo.
Python 2, usando lambda
>>> head, tail = (lambda lst: (lst[0], lst[1:]))([1, 1, 2, 3, 5, 8, 13, 21, 34, 55])
>>> head
1
>>> tail
[1, 2, 3, 5, 8, 13, 21, 34, 55]
head, tail = lst[0], lst[1:]
? se OP significa usare un letterale, allora potrebbe dividere testa e coda manualmentehead, tail = 1, [1, 2, 3, 5, 8, 13, 21, 34, 55]
lst = ...
nella riga precedente). (2) Fare head, tail = lst[0], lst[1:]
lascia il codice aperto agli effetti collaterali (considera head, tail = get_list()[0], get_list()[1:]
) ed è diverso dalla forma di Op head, tail = **some_magic applied to** [1, 1, 2, 3, 5, 8, 13, 21, 34, 55]
.
Basandosi sulla soluzione Python 2 di @GarethLatty , il seguente è un modo per ottenere una singola riga equivalente senza variabili intermedie in Python 2.
t=iter([1, 1, 2, 3, 5, 8, 13, 21, 34, 55]);h,t = [(h,list(t)) for h in t][0]
Se hai bisogno che sia a prova di eccezioni (cioè che supporti un elenco vuoto), aggiungi:
t=iter([]);h,t = ([(h,list(t)) for h in t]+[(None,[])])[0]
Se vuoi farlo senza il punto e virgola, usa:
h,t = ([(h,list(t)) for t in [iter([1,2,3,4])] for h in t]+[(None,[])])[0]