2013-05-04 15 views
5

Potrzebuję pomocy w najbardziej efektywny sposób, aby przekształcić następującą listę w słowniku:Skuteczny sposób przekonwertować listę do słownika

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

Obecnie, mam następujące:

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

Uważam jednak, że powinien istnieć skuteczniejszy sposób osiągnięcia tego samego. Dowolny pomysł ?

+4

wierzę, nie ma nic bardziej wydajny niż. Pamiętaj, że "mniej linii" to nie to samo, co "szybciej". Wszystko sprowadza się do tego, jak język rozszerza te linie. – LtWorf

+0

Moja odpowiedź na porównanie jest zaktualizowana, która porównuje powiązane odpowiedzi dotyczące krótkich (4 pozycje), długich (13312 pozycji) i bardzo długich (27262976 elementów) list. – FallenAngel

Odpowiedz

12

użycie dict() z wyrażeniem generatora:

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

Korzystanie dict-zrozumieniem (jak sugeruje @PaoloMoretti):

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

wyniki taktowanie dla 10 ** 6 elementów:

>>> 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 (": ") dla x w lis' jest wyrażeniem generatora, a nie rozumieniem listy. Dlatego nie przydziela on tymczasowej struktury danych. – Kos

+0

Tak, mój błąd, przepraszam. W każdym razie nie jest to bardziej efektywne. To jest to samo. – LtWorf

+1

@LtWorf przeczytaj: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Loops Wyrażenia LC i generatory są szybsze niż ich odpowiednik w wersji 'for' loop. –

0

Chyba lepiej jest porównać je przez czas wykonania ...

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 

Przetestowane 100.000 pętle i 3 badania dla każdej pętli. ; Jak widać, najszybszy czas wykonania należy do case1(): standard for loop.

Wynik: 1 metody liniowej nie znaczy, że są one szybsze, w rzeczywistości, podstawowy for pętla jest zazwyczaj najszybsza droga.

Aktualizacja: wyników dla listy 13312 pozycji, lista podstawowa zawiera 26 pozycji, reszta to kopie tych pozycji z listy. Timing jest obliczana ponad 1000 pętli, a najlepiej od 3 do każdej pętli

%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 

UPDATE 2: Końcowy test odbywa się z listą 27262976 łącznych elementów, podstawowe liście mają 26 przedmiotów, reszta to kopie tych elementów wtihin listę. Czas jest obliczany na 10 pętli, a najlepiej na 3 dla każdej pętli (ponieważ wykonanie bardzo długiej listy zajmuje dużo czasu).

%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

Jednak dla prawie wszystkich aplikacji wolałbym nadal przypadek 2, ponieważ jest to bardziej oczywiste, co robisz. – poke

+0

Czy masz również wyniki dla większego zestawu danych? – inf

+0

@Doke może, ale pytanie tutaj jest _efektywność_, a nie czytelność. – FallenAngel

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