Tengo una cadena que se parece a esto:
"Name1=Value1;Name2=Value2;Name3=Value3"
¿Hay una clase / función incorporada en Python que tomará esa cadena y construirá un diccionario, como si hubiera hecho esto?
dict = {
"Name1": "Value1",
"Name2": "Value2",
"Name3": "Value3"
}
He revisado los módulos disponibles pero parece que no puedo encontrar nada que coincida.
Gracias, sé cómo hacer el código relevante yo mismo, pero dado que estas soluciones tan pequeñas suelen ser campos míos esperando a suceder (es decir, alguien escribe: Name1 = 'Value1 = 2';) etc., entonces generalmente prefiero algunas pre función probada.
Entonces lo haré yo mismo.
python
string
dictionary
split
Lasse V. Karlsen
fuente
fuente
s = r'Name1='Value=2';Name2=Value2;Name3=Value3;Name4="Va\"lue;\n3"'
entrada (nota: un punto y coma dentro de una cadena entre comillas, una cita se escapa usando una barra invertida,\n
se usa escape , se usan comillas simples y dobles)?Respuestas:
No hay una función incorporada, pero puede lograr esto de manera bastante simple con una comprensión del generador:
s= "Name1=Value1;Name2=Value2;Name3=Value3" dict(item.split("=") for item in s.split(";"))
[Editar] Desde su actualización, indica que es posible que deba manejar las cotizaciones. Esto complica las cosas, dependiendo del formato exacto que esté buscando (qué caracteres de comillas se aceptan, qué caracteres de escape, etc.). Es posible que desee ver el módulo csv para ver si puede cubrir su formato. Aquí hay un ejemplo: (Tenga en cuenta que la API es un poco torpe para este ejemplo, ya que CSV está diseñado para iterar a través de una secuencia de registros, de ahí las llamadas .next () que estoy haciendo para mirar solo la primera línea. Ajustar a se adapte a sus necesidades):
>>> s = "Name1='Value=2';Name2=Value2;Name3=Value3" >>> dict(csv.reader([item], delimiter='=', quotechar="'").next() for item in csv.reader([s], delimiter=';', quotechar="'").next()) {'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1=2'}
Sin embargo, dependiendo de la estructura exacta de su formato, es posible que deba escribir su propio analizador simple.
fuente
s = "Name1='Value;2';Name2=Value2;Name3=Value3"
las comillas , intente: (nota: punto y coma en elName1
valor entre comillas ).AttributeError: '_csv.reader' object has no attribute 'next'
me arroja . Por supuesto que lo hiceimport csv
.Esto se acerca a hacer lo que querías:
>>> import urlparse >>> urlparse.parse_qs("Name1=Value1;Name2=Value2;Name3=Value3") {'Name2': ['Value2'], 'Name3': ['Value3'], 'Name1': ['Value1']}
fuente
&
o%
en la entrada.&
o%
, al menos, vale la pena mencionar que la respuesta no funciona para tales cadenas.s1 = "Name1=Value1;Name2=Value2;Name3=Value3" dict(map(lambda x: x.split('='), s1.split(';')))
fuente
Se puede hacer simplemente mediante combinación de cadenas y comprensión de listas
",".join(["%s=%s" % x for x in d.items()])
>>d = {'a':1, 'b':2} >>','.join(['%s=%s'%x for x in d.items()]) >>'a=1,b=2'
fuente
easytiger $ cat test.out test.py | sed 's/^/ /' p_easytiger_quoting:1.84563302994 {'Name2': 'Value2', 'Name3': 'Value3', 'Name1': 'Value1'} p_brian:2.30507516861 {'Name2': 'Value2', 'Name3': "'Value3'", 'Name1': 'Value1'} p_kyle:7.22536420822 {'Name2': ['Value2'], 'Name3': ["'Value3'"], 'Name1': ['Value1']} import timeit import urlparse s = "Name1=Value1;Name2=Value2;Name3='Value3'" def p_easytiger_quoting(s): d = {} s = s.replace("'", "") for x in s.split(';'): k, v = x.split('=') d[k] = v return d def p_brian(s): return dict(item.split("=") for item in s.split(";")) def p_kyle(s): return urlparse.parse_qs(s) print "p_easytiger_quoting:" + str(timeit.timeit(lambda: p_easytiger_quoting(s))) print p_easytiger_quoting(s) print "p_brian:" + str(timeit.timeit(lambda: p_brian(s))) print p_brian(s) print "p_kyle:" + str(timeit.timeit(lambda: p_kyle(s))) print p_kyle(s)
fuente
s = "Name1='Value1=2';Name2=Value2" and
csv` (como en la respuesta aceptada de Brian) oparse_qs
(como en la de Kyle) lo hará bien, mientras que el suyo generará unValueError
. El OP dice específicamente que "estas soluciones tan pequeñas suelen ser campos de minas esperando a que ocurran", por lo que quiere una solución incorporada u otra solución bien probada, y da un ejemplo que romperá su código.s.replace
no hace nada en absoluto; simplemente devuelve una nueva cadena que ignora. En segundo lugar, incluso si lo hizo bien (s = s.replace…
), eso no soluciona el problema, solo agrega uno nuevo encima. Pruébelo en mi ejemplo o en los OP.Name='Value1=2';
. Y su código no lo maneja. Y no estoy seguro de cómo desinfectaría eso sin analizarlo de alguna manera que sea tan lento comourlparse
ocsv
en primer lugar.SI su Valor1, Valor2 son solo marcadores de posición para valores reales, también puede usar la
dict()
función en combinación coneval()
.>>> s= "Name1=1;Name2=2;Name3='string'" >>> print eval('dict('+s.replace(';',',')+')') {'Name2: 2, 'Name3': 'string', 'Name1': 1}
Esto se debe a que la
dict()
función comprende la sintaxisdict(Name1=1, Name2=2,Name3='string')
. Los espacios en la cadena (por ejemplo, después de cada punto y coma) se ignoran. Pero tenga en cuenta que los valores de cadena requieren comillas.fuente
s.replace(';'
-basada solución se rompe si hay;
dentro de un valor cotizado. eval es malo y no es necesario en este caso.