Sustituya múltiples espacios en blanco por espacios en blanco únicos en Python [duplicado]

Resuelto creativz asked hace 14 años • 3 respuestas

Tengo esta cadena:

mystring = 'Here is  some   text   I      wrote   '

¿Cómo puedo sustituir los caracteres de espacio en blanco doble, triple (...) por un solo espacio, para obtener:

mystring = 'Here is some text I wrote'
creativz avatar Jan 16 '10 22:01 creativz
Aceptado

Una posibilidad simple (si prefiere evitar los RE) es

' '.join(mystring.split())

La división y la unión realizan la tarea sobre la que estás preguntando explícitamente; además, también hacen la tarea adicional de la que no hablas pero que se ve en tu ejemplo, eliminando los espacios finales ;-).

Alex Martelli avatar Jan 16 '2010 15:01 Alex Martelli

Se puede utilizar una expresión regular para ofrecer más control sobre los caracteres de espacio en blanco que se combinan.

Para hacer coincidir los espacios en blanco Unicode:

import re

_RE_COMBINE_WHITESPACE = re.compile(r"\s+")

my_str = _RE_COMBINE_WHITESPACE.sub(" ", my_str).strip()

Para que coincida únicamente con espacios en blanco ASCII:

import re

_RE_COMBINE_WHITESPACE = re.compile(r"(?a:\s+)")
_RE_STRIP_WHITESPACE = re.compile(r"(?a:^\s+|\s+$)")

my_str = _RE_COMBINE_WHITESPACE.sub(" ", my_str)
my_str = _RE_STRIP_WHITESPACE.sub("", my_str)

A veces es esencial hacer coincidir solo los espacios en blanco ASCII para mantener caracteres de control como x0b, x0c, x1c, x1d, x1e, x1f.

Referencia:

Acerca de \s:

Para patrones Unicode (str): coincide con los caracteres de espacios en blanco Unicode (que incluyen [ \t\n\r\f\v] y también muchos otros caracteres, por ejemplo, los espacios sin separación exigidos por las reglas tipográficas en muchos idiomas). Si se utiliza el indicador ASCII, solo coincide [ \t\n\r\f\v].

Acerca de re.ASCII:

Haga que \w, \W, \b, \B, \d, \D, \s y \S realicen una coincidencia solo ASCII en lugar de una coincidencia Unicode completa. Esto sólo tiene sentido para los patrones Unicode y se ignora para los patrones de bytes. Corresponde a la bandera en línea (?a).

strip()eliminará los espacios en blanco iniciales y finales.

hroest avatar Jan 16 '2010 15:01 hroest

Para completar, también puede utilizar:

mystring = mystring.strip()  # the while loop will leave a trailing space, 
                  # so the trailing whitespace must be dealt with
                  # before or after the while loop
while '  ' in mystring:
    mystring = mystring.replace('  ', ' ')

que funcionará rápidamente en cadenas con relativamente pocos espacios (más rápido que reen estas situaciones).

En cualquier escenario, la solución de división/unión de Alex Martelli funciona al menos con la misma rapidez (normalmente mucho más).

En su ejemplo, usando los valores predeterminados de timeit.Timer.repeat(), obtengo los siguientes tiempos:

str.replace: [1.4317800167340238, 1.4174888149192384, 1.4163512401715934]
re.sub:      [3.741931446594549,  3.8389395858970374, 3.973777672860706]
split/join:  [0.6530919432498195, 0.6252146571700905, 0.6346594329726258]


EDITAR:

Acabo de encontrar esta publicación que ofrece una comparación bastante larga de las velocidades de estos métodos.

David C avatar Apr 10 '2013 22:04 David C