2009-12-12 12 views
246

Me preguntaba lo que la forma más sencilla es la de convertir una lista string como la siguiente en una list:Convertir representación de cadena de la lista a la lista en Python

x = u'[ "A","B","C" , " D"]' 

Incluso en caso de que el usuario pone espacios entre las comas, y espacios dentro de las comillas. Necesito manejar eso también a:

x = ["A", "B", "C", "D"] 

en Python.

Sé que puedo quitar espacios con strip() y split() usando el operador de división y verificar en busca de letras que no sean alfabetos. Pero el código se estaba volviendo muy pesado. ¿Hay alguna función rápida de la que no tenga conocimiento?

+3

¿Qué está realmente tratando de lograr? Probablemente haya una forma mucho mejor que tratar de convertir la sintaxis de la lista de Python en una lista real ... –

+0

¿Qué versión de Python estás usando? –

+2

@Nicholas Knight: Estoy tratando de manejar las entradas del usuario en una aplicación heredada donde todas las listas se ingresaron como listas Unicode con paréntesis cuadrados. @ Mark Byers, estoy usando Python 2.6 así que el enfoque ast.literal funciona mejor – harijay

Respuesta

403
>>> import ast 
>>> x = u'[ "A","B","C" , " D"]' 
>>> x = ast.literal_eval(x) 
>>> x 
['A', 'B', 'C', ' D'] 
>>> x = [n.strip() for n in x] 
>>> x 
['A', 'B', 'C', 'D'] 

ast.literal_eval:

Con ast.literal_eval, se pueden evaluar de forma segura un nodo de expresión o una cadena que contiene una expresión de Python. La cadena o nodo proporcionado solo puede consistir en las siguientes estructuras literales de Python: cadenas, números, tuplas, listas, dictados, booleanos y Ninguno.

+2

Por comentario a continuación, esto es peligroso ya que simplemente ejecuta cualquier python que esté en la cadena. Entonces, si alguien hace una llamada para borrar todo lo que hay allí, lo hará felizmente. –

+0

Gran respuesta, luché con este problema durante una hora hasta encontrar esta respuesta. –

5

Hay una solución rápida:

x = eval('[ "A","B","C" , " D"]') 

espacios en blanco no deseados en los elementos de la lista se pueden eliminar de esta manera:

x = [x.strip() for x in eval('[ "A","B","C" , " D"]')] 
+0

esto aún conservaría los espacios dentro de las cotizaciones – tosh

+10

Esta es una invitación abierta a la ejecución de código arbitrario, NUNCA haga esto ni nada por el estilo a menos que sepa con absoluta certeza de que la entrada siempre será 100% confiable. –

+0

@tosh: no lo hará. –

9
import ast 
l = ast.literal_eval('[ "A","B","C" , " D"]') 
l = [i.strip() for i in l] 
50

El eval es peligroso - no debe ejecutar entrada del usuario.

Si tiene 2.6 o posterior, utilice ast en lugar de eval:

>>> import ast 
>>> ast.literal_eval('["A","B" ,"C" ," D"]') 
["A", "B", "C", " D"] 

Una vez que tenga que, strip las cuerdas.

Si estás en una versión anterior de Python, puede llegar muy cerca de lo que desea con una simple expresión regular:

>>> x='[ "A", " B", "C","D "]' 
>>> re.findall(r'"\s*([^"]*?)\s*"', x) 
['A', 'B', 'C', 'D'] 

Esto no es tan buena como la solución AST, por ejemplo, no maneja correctamente las comillas escapadas en cadenas. Pero es simple, no implica una evaluación peligrosa, y podría ser lo suficientemente bueno para su propósito si está en un Python más viejo sin éxito.

+0

¿Podría decirme por qué dijo "El' eval' es peligroso, no debe ejecutar la entrada del usuario "? Estoy usando 3.6 –

+0

@AaryanDewan si usa 'eval' directamente, evaluará cualquier expresión válida de python, que es potencialmente peligrosa. 'literal_eval' resuelve este problema evaluando estructuras literales Python: cadenas, números, tuplas, listas, dicts, booleanos y None. –

3

Si usted sabe que sus listas sólo contienen cadenas entre comillas, este ejemplo pyparsing le dará su lista de cadenas despojadas (aunque conservando el original Unicode-dad).

>>> from pyparsing import * 
>>> x =u'[ "A","B","C" , " D"]' 
>>> LBR,RBR = map(Suppress,"[]") 
>>> qs = quotedString.setParseAction(removeQuotes, lambda t: t[0].strip()) 
>>> qsList = LBR + delimitedList(qs) + RBR 
>>> print qsList.parseString(x).asList() 
[u'A', u'B', u'C', u'D'] 

Si sus listas pueden tener más tipos de datos, o incluso contener listas dentro de listas, entonces usted tendrá una visión más completa de gramática - como this one en el pyparsing wiki, que se encargará de tuplas, listas, enteros, flotadores, y cadenas citadas. Funcionará con las versiones de Python de nuevo a 2.4.

+0

me harías saber cómo usar "parseString(). AsList()", si tengo este tipo de cadena: '["A", "B", "C", ["D"]]', como ha declarado que pyparsing también puede hacer eso. pero o no parece haber encontrado la manera correcta de hacerlo. –

+0

"Si sus listas pueden tener más tipos de datos, o incluso contener listas dentro de listas, necesitará una gramática más completa" - consulte el enlace que proporcioné en mi respuesta para un analizador que manejará listas anidadas y varios otros tipos de datos . – PaulMcG

7

Suponiendo que todas sus entradas son listas y que las comillas dobles en la entrada en realidad no importan, esto se puede hacer con una simple regexp replace. Es un poco perl-y pero funciona como un encanto.Tenga en cuenta también que el resultado ahora es una lista de cadenas Unicode, no especificó que lo necesitaba, pero parece tener sentido dado la entrada Unicode.

import re 
x = u'[ "A","B","C" , " D"]' 
junkers = re.compile('[[" \]]') 
result = junkers.sub('', x).split(',') 
print result 
---> [u'A', u'B', u'C', u'D'] 

La variable Junkers contiene una expresión regular compilada (para velocidad) de todos los caracteres que no queremos, utilizando] como un personaje requiere algún truco barra invertida. El re.sub reemplaza a todos estos caracteres sin nada, y dividimos la cadena resultante en las comas.

Tenga en cuenta que esto también elimina espacios de las entradas internas u '["oh no"]' ---> [u'ohno ']. Si esto no es lo que quería, la expresión regular necesita ser mejorada un poco.

7

con numpy esto está funcionando de una manera muy sencilla

x = u'[ "A","B","C" , " D"]' 
list_string = str(x) 
import numpy as np 
print np.array(list_string) 

da

>>> 
[ "A","B","C" , " D"] 
+4

Esto no funciona. Simplemente hace una matriz de 0 d de la cadena. Cualquier operación de matriz, como acceder a un elemento, falla con un error. – River

30

El módulo json es una mejor solución siempre que haya un Stringified lista de diccionarios. La función json.loads(your_data) se puede utilizar para convertirla en una lista.

>>> import json 
>>> x = u'[ "A","B","C" , " D"]' 
>>> json.loads(x) 
[u'A', u'B', u'C', u' D'] 

Del mismo modo

>>> x = u'[ "A","B","C" , {"D":"E"}]' 
>>> json.loads(x) 
[u'A', u'B', u'C', {u'D': u'E'}] 
+0

, sin embargo, no quiero la lista devuelta en formato Unicode. pero parece que incluso si elimino u '' de la cadena, StillSt trata los datos como unicode. –

+1

Esto funciona para ints pero no para cadenas en mi caso porque cada cadena es única citada, no doble, suspiro. –

Cuestiones relacionadas