2010-07-21 8 views
8

Ho una lista di stringhe analizzate da qualche parte, nel seguente formato:Modo Pythonic per trasformare un elenco di stringhe in un dizionario con le stringhe con indici dispari come chiavi e quelli con indici pari come valori?

[key1, value1, key2, value2, key3, value3, ...] 

mi piacerebbe creare un dizionario in base a questa lista, in questo modo:

{key1:value1, key2:value2, key3:value3, ...} 

Un normale for il loop con offset dell'indice probabilmente farebbe il trucco, ma mi chiedo se c'è un modo Python di farlo. La comprensione delle liste sembra interessante, ma non riesco a capire come applicarle a questo particolare problema.

Qualche idea?

risposta

13

Si può provare:

dict(zip(l[::2], l[1::2])) 

Spiegazione: abbiamo diviso la lista in due liste, una delle anche e uno degli elementi dispari, prendendoli a passi di due a partire dal primo o il secondo elemento (quello è il l[::2] e l[1::2]). Quindi utilizziamo il zip incorporato nei due elenchi in un elenco di coppie. Infine, chiamiamo dict per creare un dizionario da queste coppie chiave-valore.

Questo è ~4n in tempo e ~4n nello spazio, incluso il dizionario finale. Probabilmente è più veloce di un ciclo, però, dal momento che la zip, dict, e gli operatori affettatrici sono scritti in C.

+0

Esattamente quello di cui avevo bisogno e ben spiegato, grazie un pavpanchekha sacco! – KennyDeriemaeker

0
result = dict(grouper(2, L)) 

grouper è una funzione che forma le coppie in un elenco, è dato nella itertools receipes:

def grouper(n, iterable, fillvalue=None): 
    "grouper(3, 'ABCDEFG', 'x') --> ABC DEF Gxx" 
    args = [iter(iterable)] * n 
    return izip_longest(fillvalue=fillvalue, *args) 

dict prende un elenco di coppie (key,value) e ne fa un dettato.

Si potrebbe anche scrivere result = dict(zip(*[iter(L)]*2)) e confondere maggior parte dei lettori :-)

+0

'result = dict (zip (* [iter (L)] * 2))' non è garantito il funzionamento (zip non garantisce l'ordine di valutazione dei suoi argomenti). Dovresti usare 'result = dict (izip (* [iter (L)] * 2))' invece che oltre ad essere un modello di chiarezza (!) Che garantisce l'ordine corretto di valutazione. – Duncan

+1

@Ducan: dove hai preso quell'idea (sbagliata)? Vedi http://docs.python.org/library/functions.html#zip 'izip' è solo la versione iteratore di' zip'. –

3
In [71]: alist=['key1', 'value1', 'key2', 'value2', 'key3', 'value3'] 

In [72]: dict(alist[i:i+2] for i in range(0,len(alist),2)) 
Out[72]: {'key1': 'value1', 'key2': 'value2', 'key3': 'value3'} 
1

Oltre alla soluzione a breve e perfettamente soddisfacente di pavpanchekha, è possibile utilizzare un generatore di espressione (una list comprehension è solo un'espressione generatore alimentato a il costruttore lista - in realtà è più potente und universale) per il bene più:

dict((l[i], l[l+1]) for i in range(0, len(l)-1, 2)) 

Oltre ad essere davvero cool e funzionale, è anche un algoritmo migliore: a meno che l'attuazione di dict è especiall y stupido (considerato improbabile che sia un built-in), questo consumerà la stessa quantità di memoria per ogni dimensione di l (ad es. gira in costante O (1) spazio) dato che elabora una coppia alla volta invece di creare una lista completamente nuova di tuple.

5

Una bella occasione di mostrare il mio linguaggio python preferito:

>>> S = [1,2,3,4,5,6] 
>>> dict(zip(*[iter(S)]*2)) 
{1: 2, 3: 4, 5: 6} 

Quella linea ingannevole passa due argomenti per zip() in cui ogni argomento è il stessa iteratore su S. zip() crea tuple 2-item, tirando da l'iteratore su zip ogni volta. dict() quindi converte quelle tuple in un dizionario.

estrapolare:

S = [1,2,3,4,5,6] 

I = iter(S) 
dict(zip(I,I)) 
+1

È ECCEZIONALE. Principali punti brownie! – katrielalex

Problemi correlati