Frage

Ich bin ein paar Mal auf dieses Problem gestoßen und kann keine einfache Lösung finden. Sagen Sie, ich habe eine Zeichenfolge

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

Ich möchte das in ein Wörterbuch umwandeln, wobei A, B und C der Schlüssel und 0, 1 und 3 ihre jeweiligen Werte sind (umgewandelt in INT). Offensichtlich kann ich das tun:

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

Aber das mag das für Loop nicht wirklich, es scheint so einfach, dass Sie es in eine Art Listenverständnisausdruck konvertieren können. Und das funktioniert für etwas einfachere Fälle, in denen die val Kann eine Zeichenfolge sein.

dic = dict([entry.split('=') for entry in list])

Ich muss jedoch Val in einen in der Fliege umwandeln und so etwas tun, ist syntaktisch falsch.

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

Meine Frage lautet also: Gibt es eine Möglichkeit, die für Schleife mit Listenverständnis zu beseitigen? Wenn nicht, gibt es eine eingebaute Python -Methode, die das für mich tun wird?

War es hilfreich?

Lösung

Meinst du das?

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

Andere Tipps

Wie wäre es mit einem One-Liner ohne Listenverständnis?

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

Versuchen Sie es mit dem nächsten:

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

Manchmal mag ich diesen Ansatz, besonders wenn die Logik für die Erstellung von Schlüssel und Werten 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()))

Heutzutage sollten Sie wahrscheinlich ein Wörterbuchverständnis verwenden, das in 2.7 eingeführt wurde:

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

Das Wörterbuchverständnis ist schneller und glänzender (und meiner Meinung nach lesbarer).

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
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

Drucke

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

Ich würde das tun:

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

Ich mag die Lösung von S.lott, aber ich habe eine andere Möglichkeit entwickelt.
Da Sie bereits eine Zeichenfolge haben, die irgendwie so ähnelt, wie Sie das schreiben würden, können Sie sie einfach an die Python -Syntax anpassen 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

Der Regex hier ist ziemlich roh und fängt nicht alle möglichen Python -Kennungen auf, aber ich wollte es einfach für den Einfachheit halber einfach halten. Wenn Sie die Kontrolle darüber haben, wie die Eingangszeichenfolge erzeugt wird, generieren Sie sie einfach nach der Python -Syntax und bewerten Sie sie weg. Aber natürlich sollten Sie zusätzliche Vernunftprüfungen durchführen, um sicherzustellen, dass dort kein Code injiziert wird!

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top