2013-05-04 12 views
5

ich Hilfe auf die effizienteste Art und Weise müssen Sie die folgende Liste in einem Wörterbuch zu konvertieren:Effiziente Möglichkeit, eine Liste zu konvertieren Zum Wörterbuch

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

Derzeit ich folgendes:

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

Ich glaube jedoch, dass es einen effizienteren Weg geben sollte, dasselbe zu erreichen. Irgendeine Idee ?

+4

Ich glaube, es gibt nichts, was effizienter als das. Denken Sie daran, dass "weniger Zeilen" nicht gleich "schneller" ist. Es läuft alles darauf hinaus, wie die Sprache diese Linien erweitert. – LtWorf

+0

Meine Vergleichsantwort wird aktualisiert, die verwandte Antworten für kurze (4 Elemente), lange (13312 Elemente) und sehr lange (27262976 Elemente) Listen vergleicht. – FallenAngel

Antwort

12

Verwendung dict() mit einem Generator Ausdruck:

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

Mit dict-Verständnis (wie von @PaoloMoretti vorgeschlagen):

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

Timing-Ergebnisse für 10 ** 6 Artikel:

>>> 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 (": ") für x in lis' ist ein Generatorausdruck, kein Listenverständnis. Daher wird keine temporäre Datenstruktur zugewiesen. – Kos

+0

Ja, mein Fehler, tut mir leid. Jedenfalls ist es nicht effizienter. Es ist das gleiche. – LtWorf

+1

@LtWorf lesen Sie dies: http://wiki.python.org/moin/PythonSpeed/PerformanceTips#Loops LC-und Generator-Ausdrücke sind schneller als ihre äquivalente 'for' Loop-Version. –

0

Ich denke, es besser ist, sie durch die Ausführungszeit ...

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 

für 100.000 Schlaufen und 3 Test für jede Schleife Getestete zu vergleichen. Wie Sie sehen können, gehört die schnellste Ausführungszeit zu case1(): Standard for loop.

Ergebnis: 1 Liner Methoden bedeuten nicht, dass sie schneller sind, in der Tat, grundlegende for Schleife ist in der Regel der schnellste Weg zu gehen.

Update: Ergebnisse für eine Liste von 13312 Artikel, Grundliste haben 26 Artikel, Rest sind die Kopien dieser Artikel in der Liste. Timing berechnet über 1000 Loops und am besten von 3 für jede Schleife

%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: Abschlussprüfung erfolgt mit einer Liste von 27262976 Gesamtanzahl der Objekte, Grundliste 26 Produkte haben, Rest sind die Kopien dieser Artikel mit der Liste. Das Timing wird über 10 Schleifen und das Beste von 3 für jede Schleife berechnet (da die Ausführung einer sehr langen Liste viel Zeit in Anspruch nimmt).

%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

Aber für fast alle Anwendungen würde ich noch Fall 2 bevorzugen, da es nur mehr offensichtlich ist, was Sie tun. – poke

+0

Haben Sie auch Ergebnisse für einen größeren Datensatz? – inf

+0

@poke vielleicht, aber Frage hier ist Effizienz, nicht Lesbarkeit. – FallenAngel

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