2013-05-04 11 views
5

ho bisogno di aiuto nel modo più efficiente per convertire la seguente lista in un dizionario:modo efficiente per convertire un elenco al dizionario

l = ['A:1','B:2','C:3','D:4'] 

Allo stato attuale, effettuare le seguenti operazioni:

mydict = {} 
for e in l: 
    k,v = e.split(':') 
    mydict[k] = v 

Tuttavia, credo che ci dovrebbe essere un modo più efficiente per ottenere lo stesso. Qualche idea ?

+4

credo che non ci sia qualcosa di più efficiente di quello. Ricorda che "meno righe" non è uguale a "più veloce". Tutto si riduce a come il linguaggio espande quelle linee. – LtWorf

+0

La mia risposta di confronto viene aggiornata, che confronta le risposte correlate per gli elenchi brevi (4 elementi), lungo (13312 elementi) e molto lungo (27262976 voci). – FallenAngel

risposta

12

uso dict() con un generatore di espressione:

>>> lis=['A:1','B:2','C:3','D:4'] 
>>> dict(x.split(":") for x in lis) 
{'A': '1', 'C': '3', 'B': '2', 'D': '4'} 

Uso dict-comprensione (come suggerito da @PaoloMoretti):

>>> {k:v for k,v in (e.split(':') for e in lis)} 
{'A': '1', 'C': '3', 'B': '2', 'D': '4'} 

risultati temporizzazione per 10 ** 6 elementi:

>>> from so import * 
>>> %timeit case1() 
1 loops, best of 3: 2.09 s per loop 
>>> %timeit case2() 
1 loops, best of 3: 2.03 s per loop 
>>> %timeit case3() 
1 loops, best of 3: 2.17 s per loop 
>>> %timeit case4() 
1 loops, best of 3: 2.39 s per loop 
>>> %timeit case5() 
1 loops, best of 3: 2.82 s per loop 

so.py:

a = ["{0}:{0}".format(i**2) for i in xrange(10**6)] 

def case1(): 
    dc = {} 
    for i in a: 
     q, w = i.split(':') 
     dc[q]=w 

def case2(): 
    dict(x.split(":") for x in a) 


def case3(): 
    {k:v for k,v in (e.split(':') for e in a)} 

def case4(): 
    dict([x.split(":") for x in a]) 

def case5(): 
    {x.split(":")[0] : x.split(":")[1] for x in a} 
+0

@LtWorf 'x.split (": ") per x in lis' è un'espressione di generatore, non una comprensione di lista. Quindi non assegna una struttura dati temporanea – Kos

+0

Sì, mio ​​errore, mi dispiace. Comunque non è più efficiente. È lo stesso. – LtWorf

+1

@LtWorf leggi questo: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Loops Le espressioni di LC e di generatore sono più veloci della loro versione equivalente di 'for' loop. –

0

Credo che sia meglio per confrontarli con il tempo di esecuzione ...

a = ['A:1','B:2','C:3','D:4'] 

def case1(): 
    dc = {} 
    for i in a: 
     q, w = i.split(':') 
     dc[q]=w 

def case2(): 
    dict(x.split(":") for x in a) 


def case3(): 
    {x.split(":")[0] : x.split(":")[1] for x in a} 


%timeit -n 100000 case1() 
>> 100000 loops, best of 3: 1.95 us per loop 


%timeit -n 100000 case2() 
>> 100000 loops, best of 3: 3.05 us per loop 


%timeit -n 100000 case3() 
>> 100000 loops, best of 3: 3.39 us per loop 

Testato per 100.000 loop e 3 test per ogni ciclo. Come puoi vedere, il tempo di esecuzione più veloce appartiene a case1(): standard for loop.

Risultato: 1 metodi di copertina non significa che essi sono più veloci, infatti, di base for ciclo è in genere il modo più veloce per andare.

Aggiornamento: risultati per un elenco di 13312 articoli, l'elenco di base contiene 26 elementi, il resto sono le copie di quegli elementi che contengono l'elenco. Timing è calcolato oltre 1000 loop e meglio di 3 per ogni ciclo

%timeit -n 1000 case3() 
1000 loops, best of 3: 9.49 ms per loop 

%timeit -n 1000 case2() 
1000 loops, best of 3: 5.79 ms per loop 

%timeit -n 1000 case1() 
1000 loops, best of 3: 5.55 ms per loop 

Aggiornamento 2: Prova finale avviene con una lista di 27262976 elementi totali, lista di base hanno 26 articoli, resto sono le copie di tali articoli wtihin la lista. Il tempo è calcolato su 10 loop e il migliore di 3 per ogni loop (poiché l'esecuzione di una lista molto lunga richiede molto tempo).

%timeit -n 10 case1() 
10 loops, best of 3: 11.4 s per loop 

%timeit -n 10 case2() 
10 loops, best of 3: 12.1 s per loop 

%timeit -n 10 case3() 
10 loops, best of 3: 20.2 s per loop 
+0

Ma per quasi tutte le applicazioni preferirei ancora il caso 2 in quanto è più ovvio di quello che stai facendo. – poke

+0

Hai anche dei risultati per un set di dati più grande? – inf

+0

forse @poke, ma la domanda qui è _efficienza_, non leggibilità. – FallenAngel

1
>>> dict(map(lambda s: s.split(":"), ["A:1", "B:2", "C:3", "D:4"])) 
{'A': '1', 'C': '3', 'B': '2', 'D': '4'} 
Problemi correlati