convertir la cadena a dict utilizando lista de comprensión

Me he encontrado con este problema unas cuantas veces y parece que no puedo encontrar una solución simple. Di que tengo una cuerda

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

Quiero convertir eso en un diccionario con a, byc siendo la clave y 0, 1 y 3 siendo sus valores respectivos (convertidos a int). Obviamente puedo hacer esto:

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

Pero realmente no me gusta eso para el bucle. Parece tan simple que deberías poder convertirlo en algún tipo de expresión de comprensión de lista. Y eso funciona para casos un poco más simples donde el val puede ser una cadena.

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

Sin embargo, necesito convertir val en un int sobre la marcha y hacer algo como esto es sintácticamente incorrecto.

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

Así que mi pregunta es: ¿hay una manera de eliminar el bucle for utilizando la comprensión de lista? Si no es así, ¿hay algún método Python integrado que haga eso por mí?

¿Quieres decir esto?

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

¿Qué tal un one-liner sin lista de comprensión?

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

Intenta lo siguiente:

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

A veces me gusta este enfoque, especialmente cuando la lógica para crear claves y valores es más complicada:

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

Hoy en día probablemente deberías usar un diccionario de comprensión, introducido en 2.7:

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

La comprensión del diccionario es más rápida y shiny (y, en mi opinión, más legible).

 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 

huellas dactilares

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

Yo haría esto:

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

Me gusta la solución de S.Lott, pero se me ocurrió otra posibilidad.
Como ya tienes una cadena parecida a la forma en que lo escribirías, puedes adaptarla a la syntax de Python y luego evaluarla () 🙂

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

La expresión regular aquí es bastante simple y no detectará todos los posibles identificadores de Python, pero quería mantenerlo simple por simplicidad. Por supuesto, si tiene control sobre cómo se genera la cadena de entrada, solo genérela de acuerdo con la syntax de python y evalúela. ¡PERO, por supuesto, debe realizar comprobaciones adicionales de sanidad para asegurarse de que no se inyecte ningún código allí!