15

Ich bin auf dieses Problem ein paar Mal gestoßen und kann nicht scheinen, eine einfache Lösung herauszufinden. Sagen, ich habe einen Stringkonvertiere string zu dict mit list Verständnis in Python

string = "a=0 b=1 c=3" 

I, das in ein Wörterbuch mit einem konvertierenden, b und c als Schlüssel und 0, 1, 3 und ihre jeweiligen Werte zu sein (in int umgewandelt). Natürlich kann ich dies tun:

list = string.split() 
    dic = {} 
    for entry in list: 
     key, val = entry.split('=') 
     dic[key] = int(val) 

Aber ich weiß nicht wirklich wie die for-Schleife Es scheint so einfach, dass Sie sollten in der Lage, es zu irgendeiner Art von Liste Verständnis Ausdruck zu konvertieren. Und das funktioniert für etwas einfachere Fälle, wo die val eine Zeichenfolge sein kann.

Allerdings muss ich Val zu einem Int on the fly konvertieren und etwas wie das ist syntaktisch falsch.

dic = dict([[entry[0], int(entry[1])] for entry.split('=') in list]) 

Also meine Frage ist: Gibt es eine Möglichkeit, die for-Schleife Verständnis mit Liste zu beseitigen? Wenn nicht, gibt es eine eingebaute Python-Methode, die das für mich tun wird?

+0

Hinweis: Verwenden Sie keine Funktionen als Variablennamen gebaut ('string',' list', etc.) –

Antwort

29

Meinst du das?

>>> dict((n,int(v)) for n,v in (a.split('=') for a in string.split())) 
{'a': 0, 'c': 3, 'b': 1} 
+4

Während das ist cool, ich glaube, ich bevorzuge die Version in der ursprünglichen Frage von einem langfristigen Standpunkt der Codepflege. Der Code in der ursprünglichen Frage ist klar und offensichtlich, das obige erfordert mehrere zehn Sekunden zu grok. –

+1

@ Bryan Oakley: Ich stimme zu. Die Frage ("Gibt es einen Weg, die for-Schleife mit Listenverständnis zu beseitigen") hat eine Antwort. Die Antwort mag jedoch nicht das sein, was sie wirklich wollten. –

+1

Ja das ist, was ich gesucht habe. Vielen Dank. @Bryan: Ich fange an zu denken, dass es vielleicht eine gute Idee ist, diese For-Schleife zu halten. Trotzdem weiß ich zumindest jetzt, wie man das in einer Zeile macht. – Pavel

1
from cgi import parse_qsl 
text = "a=0 b=1 c=3" 
dic = dict((k, int(v)) for k, v in parse_qsl(text.replace(' ', '&'))) 
print dic 

druckt

{'a': 0, 'c': 3, 'b': 1} 
+0

Nizza ......... 15. –

-3

mag ich S.Lott-Lösung, aber ich kam mit einer anderen Möglichkeit auf.
Da Sie bereits eine Zeichenfolge ähnelt irgendwie die Art und Weise haben Sie schreiben, dass möchten, können Sie es an Python Syntax anpassen gerade und dann eval() it :)

import re 
string = "a=0 b=1 c=3" 
string2 = "{"+ re.sub('(|^)(?P<id>\w+)=(?P<val>\d+)', ' "\g<id>":\g<val>,', string) +"}" 
dict = eval(string2) 
print type(string), type(string2), type(dict) 
print string, string2, dict 

Die Regex hier ziemlich roh ist und gewann‘ t fangen alle möglichen Python-Identifikatoren, aber ich wollte es der Einfachheit halber einfach halten. Natürlich, wenn Sie Kontrolle darüber haben, wie die Eingabe-String generiert wird, nur generieren Sie es nach Python-Syntax und eval weg. ABER natürlich sollten Sie zusätzliche Gesundheitschecks durchführen, um sicherzustellen, dass dort kein Code injiziert wird!

+2

wollten Sie das einfach halten? nicht gemein zu sein oder jemanden auszuwählen, aber wo ist das einfach? – Nope

3

Wie wäre es mit einem Einzeiler ohne Listenverständnis?

foo="a=0 b=1 c=3" 
ans=eval('dict(%s)'%foo.replace(' ',','))) 
print ans 
{'a': 0, 'c': 3, 'b': 1} 
+0

Ich weiß, wie Eval funktioniert, aber ich habe Schwierigkeiten, dies zu verstehen – Ajay

+1

Die foo.replace() verwandelt "a = 0 b = 1 c = 3" in "a = 0, b = 1, c = 3". Die String-Formatierung erzeugt eine neue Zeichenfolge "dict (a = 0, b = 1, c = 3)". Das Auslesen dieser Zeichenfolge erzeugt das gewünschte Diktat. –

+0

Es dauerte eine Weile zu verstehen. – Ajay

3

Versuchen Sie die nächste:

dict([x.split('=') for x in s.split()]) 
+1

OP wollte das zweite Element der Liste in eine ganze Zahl umgewandelt werden. – hughdbrown

2

ich manchmal wie dieser Ansatz, vor allem, wenn die Logik für Schlüssel und Werte machen komplizierter ist:

s = "a=0 b=1 c=3" 

def get_key_val(x): 
    a,b = x.split('=') 
    return a,int(b) 

ans = dict(map(get_key_val,s.split())) 
0

Ich würde dies tun:

def kv(e): return (e[0], int(e[1])) 
d = dict([kv(e.split("=")) for e in string.split(" ")]) 
2

Heutzutage s hould wahrscheinlich ein Wörterbuch Verständnis verwenden, eingeführt in 2.7:

mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())} 

Das Wörterbuch Verständnis ist schneller und glänzendere (und meiner Meinung nach, besser lesbar).

from timeit import timeit 

setup = """mystring = "a=0 b=1 c=3\"""" 
code1 = """mydict = dict((n,int(v)) for n,v in (a.split('=') for a in mystring.split()))""" # S.Lott's code 
code2 = """mydict = {key: int(value) for key, value in (a.split('=') for a in mystring.split())}""" 

print timeit(code1, setup=setup, number=10000) # 0.115524053574 
print timeit(code2, setup=setup, number=10000) # 0.105328798294