Dividido por comas y espacios en blanco en Python

346

Tengo un código de Python que se divide en comas, pero no elimina el espacio en blanco:

>>> string = "blah, lots  ,  of ,  spaces, here "
>>> mylist = string.split(',')
>>> print mylist
['blah', ' lots  ', '  of ', '  spaces', ' here ']

Prefiero terminar con espacios en blanco eliminados así:

['blah', 'lots', 'of', 'spaces', 'here']

Soy consciente de que podría recorrer la lista y eliminar () cada elemento, pero, como se trata de Python, supongo que hay una manera más rápida, fácil y elegante de hacerlo.

Mr_Chimp
fuente

Respuestas:

594

Utilice la comprensión de la lista: más simple e igual de fácil de leer que un forbucle.

my_string = "blah, lots  ,  of ,  spaces, here "
result = [x.strip() for x in my_string.split(',')]
# result is ["blah", "lots", "of", "spaces", "here"]

Ver: documentos de Python sobre la comprensión de la lista
Una buena explicación de 2 segundos de la comprensión de la lista.

Sean Vieira
fuente
1
¡Super bien! Agregué un elemento de la siguiente manera para eliminar las entradas de la lista en blanco. > text = [x.strip () para x en text.split ('.') if x! = '']
RandallShanePhD
@Sean: ¿el código de Python no válido / incompleto era tu "intención original de la publicación"? Según los wankers de revisión, fue: stackoverflow.com/review/suggested-edits/21504253 . ¿Puede decirles lo contrario haciendo la corrección si están equivocados (nuevamente)?
Forraje
El original se copió de un REPL (si no recuerdo mal) y el objetivo era comprender el concepto subyacente (usar la comprensión de la lista para realizar una operación), pero tiene razón, tiene más sentido si ve esa comprensión de la lista produce una nueva lista.
Sean Vieira
24

Dividir usando una expresión regular. Tenga en cuenta que hice el caso más general con espacios iniciales. La comprensión de la lista es eliminar las cadenas nulas en la parte delantera y trasera.

>>> import re
>>> string = "  blah, lots  ,  of ,  spaces, here "
>>> pattern = re.compile("^\s+|\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['blah', 'lots', 'of', 'spaces', 'here']

Esto funciona incluso si ^\s+no coincide:

>>> string = "foo,   bar  "
>>> print([x for x in pattern.split(string) if x])
['foo', 'bar']
>>>

He aquí por qué necesitas ^ \ s +:

>>> pattern = re.compile("\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['  blah', 'lots', 'of', 'spaces', 'here']

¿Ves los espacios principales en bla?

Aclaración: arriba usa el intérprete de Python 3, pero los resultados son los mismos en Python 2.

tbc0
fuente
8
Creo que [x.strip() for x in my_string.split(',')]es más pitónico para la pregunta formulada. Tal vez hay casos en los que mi solución es necesaria. Actualizaré este contenido si me encuentro con uno.
tbc0
¿Por qué es ^\s+necesario? He probado su código sin él y no funciona, pero no sé por qué.
laike9m
Si uso re.compile("^\s*,\s*$"), el resultado es [' blah, lots , of , spaces, here '].
laike9m
@ laike9m, actualicé mi respuesta para mostrarle la diferencia. ^\s+hace. Como puede ver por sí mismo, ^\s*,\s*$tampoco devuelve los resultados deseados. Entonces, si desea dividir con una expresión regular, use ^\s+|\s*,\s*|\s+$.
tbc0
La primera coincidencia está vacía si el patrón inicial (^ \ s +) no coincide, por lo que obtiene algo como ['', 'foo', 'bar'] para la cadena "foo, bar".
Steeve McCauley
21

Vine a agregar:

map(str.strip, string.split(','))

pero vio que Jason Orendorff ya lo había mencionado en un comentario .

Al leer el comentario de Glenn Maynard en la misma respuesta, sugiriendo listas de comprensión sobre el mapa, comencé a preguntarme por qué. Asumí que se refería a razones de rendimiento, pero, por supuesto, podría haberlo hecho por razones estilísticas, o algo más (¿Glenn?).

Entonces, una prueba rápida (¿posiblemente defectuosa?) En mi caja aplicando los tres métodos en un bucle reveló:

[word.strip() for word in string.split(',')]
$ time ./list_comprehension.py 
real    0m22.876s

map(lambda s: s.strip(), string.split(','))
$ time ./map_with_lambda.py 
real    0m25.736s

map(str.strip, string.split(','))
$ time ./map_with_str.strip.py 
real    0m19.428s

haciendo map(str.strip, string.split(','))el ganador, aunque parece que todos están en el mismo estadio.

Ciertamente, aunque el mapa (con o sin lambda) no necesariamente debe descartarse por razones de rendimiento, y para mí es al menos tan claro como una comprensión de la lista.

Editar:

Python 2.6.5 en Ubuntu 10.04

Sean
fuente
15

Simplemente quite el espacio en blanco de la cadena antes de dividirlo.

mylist = my_string.replace(' ','').split(',')
usuario489041
fuente
10
Es un problema si los elementos separados por comas contienen espacios incrustados, por ejemplo "you just, broke this".
Robert Rossney el
1
Geeze, un -1 para esto. Ustedes chicos son duros. Resolvió su problema, siempre que sus datos de muestra fueran solo palabras y no se especificara que los datos serían frases. Pero w / e, supongo que así es como ustedes ruedan por aquí.
user489041
Bueno, gracias de todos modos, usuario. Para ser justos, pedí específicamente dividir y luego strip () y strip elimina espacios en blanco iniciales y finales y no toca nada en el medio. Sin embargo, un ligero cambio y su respuesta funcionaría perfectamente: mylist = mystring.strip (). Split (',') aunque no sé si esto es particularmente eficiente.
Mr_Chimp
12

Sé que esto ya ha sido respondido, pero si terminas haciendo esto mucho, las expresiones regulares pueden ser una mejor manera de hacerlo:

>>> import re
>>> re.sub(r'\s', '', string).split(',')
['blah', 'lots', 'of', 'spaces', 'here']

El \sCoincide con cualquier carácter de espacio en blanco, y acabamos de sustituirla por una cadena vacía ''. Puede encontrar más información aquí: http://docs.python.org/library/re.html#re.sub

Brad Montgomery
fuente
3
Su ejemplo no funcionaría en cadenas que contienen espacios. "para, por ejemplo, este" se convertiría en "para", "por ejemplo", "uno". No digo que sea una MALA solución (funciona perfectamente en mi ejemplo) ¡solo depende de la tarea en la mano!
Mr_Chimp 01 de
Sí, eso es muy correcto! Probablemente podría ajustar la expresión regular para que pueda manejar cadenas con espacios, pero si la comprensión de la lista funciona, diría que se quede con ella;)
Brad Montgomery
2
import re
result=[x for x in re.split(',| ',your_string) if x!='']

Esto funciona bien para mi.

Zieng
fuente
2

re (como en las expresiones regulares) permite dividir varios caracteres a la vez:

$ string = "blah, lots  ,  of ,  spaces, here "
$ re.split(', ',string)
['blah', 'lots  ', ' of ', ' spaces', 'here ']

Esto no funciona bien para su cadena de ejemplo, pero funciona bien para una lista separada por comas. Para su cadena de ejemplo, puede combinar el poder re.split para dividir en patrones regex para obtener un efecto de "división en esto o aquello".

$ re.split('[, ]',string)
['blah',
 '',
 'lots',
 '',
 '',
 '',
 '',
 'of',
 '',
 '',
 '',
 'spaces',
 '',
 'here',
 '']

Desafortunadamente, eso es feo, pero a filterhará el truco:

$ filter(None, re.split('[, ]',string))
['blah', 'lots', 'of', 'spaces', 'here']

Voila!

Dannid
fuente
2
¿Por qué no solo re.split(' *, *', string)?
Paul Tomblin
44
@PaulTomblin buena idea. También se puede haber hecho esto: re.split('[, ]*',string)para el mismo efecto.
Dannid
Dannid me di cuenta después de escribir que no elimina espacios en blanco al principio y al final como lo hace la respuesta de @ tbc0.
Paul Tomblin
@PaulTomblinheh, y mi refutación [, ]*deja una cadena vacía al final de la lista. Creo que el filtro sigue siendo algo bueno para tirar allí, o apegarse a la comprensión de la lista como lo hace la respuesta principal.
Dannid
1

map(lambda s: s.strip(), mylist)sería un poco mejor que hacer un bucle explícito. O para todo al mismo tiempo:map(lambda s:s.strip(), string.split(','))

usuario470379
fuente
10
Consejo: cada vez que te encuentres usando map, especialmente si lo estás usando lambda, verifica dos veces para ver si deberías usar una lista de comprensión.
Glenn Maynard
11
Puedes evitar la lambda con map(str.strip, s.split(',')).
Jason Orendorff
1
s = 'bla, buu, jii'

sp = []
sp = s.split(',')
for st in sp:
    print st
Parikshit Pandya
fuente
1
import re
mylist = [x for x in re.compile('\s*[,|\s+]\s*').split(string)]

Simplemente, coma o al menos un espacio en blanco con / sin espacios en blanco anteriores / posteriores.

¡Por favor, inténtalo!

GyuHyeon Choi
fuente
0

map(lambda s: s.strip(), mylist)sería un poco mejor que hacer un bucle explícito.
O para todo al mismo tiempo:

map(lambda s:s.strip(), string.split(','))

Eso es básicamente todo lo que necesitas.

DJbigpenis
fuente