2009-08-13 50 views
5

tengo una cadena que tipo de parece a esto:colapso de los espacios en blanco en una cadena

"stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" 

y quiero a quitarse toda la puntuacion, hacer que todo en mayúsculas y contraer todos los espacios en blanco para que se parezca a esto:

"STUFF MORE STUFF STUFF DD" 

¿Esto es posible con una expresión regular o necesito combinar más de dos? Esto es lo que tengo hasta ahora:

def normalize(string): 
    import re 

    string = string.upper() 

    rex = re.compile(r'\W') 
    rex_s = re.compile(r'\s{2,}') 

    result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
    result = rex.sub('', result) # this reduces all those spaces 

    return result 

Lo único que no funciona es el colapso de los espacios en blanco. ¿Algunas ideas?

Respuesta

15

Aquí es un enfoque de un solo paso (pero la realidad uppercasing utiliza un método de cadena - mucho más simple!):

rex = re.compile(r'\W+') 
result = rex.sub(' ', strarg).upper() 

donde strarg es el argumento de cadena ( No utilice nombres ese shadow builtins o módulos de biblioteca estándar, por favor).

+0

Estoy de acuerdo en que esta sería definitivamente la forma más sencilla de abordar el problema. – Amber

+1

Supongo que debería ser "cadena" y no "resultado" en el argumento de rex.sub? ¿O solo está reemplazando parte del código del usuario? –

+1

@Brooks, tienes razón - SOY TAN adverso a seguir los nombres de los módulos integrados y estándar, que cualquier cosa PERO la cadena voló fuera de mi alcance. Déjame editar para arreglar, ¡y gracias! –

3
result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
result = rex.sub('', result) # this reduces all those spaces 

Porque escribió y olvidó usar rex_s para la segunda llamada. Además, debe sustituir al menos un espacio de nuevo o terminará con una brecha de espacio múltiple que no se convertirá en ningún espacio, en lugar de un espacio de espacio único.

result = rex.sub(' ', string) # this produces a string with tons of whitespace padding 
result = rex_s.sub(' ', result) # this reduces all those spaces 
+0

buena captura por parte tipo. Me di cuenta de eso momentos después de publicar. me ganaste antes de tener la oportunidad de editar OMG – priestc

+0

Sugiero que eches un vistazo al código de Alex: es una forma mucho más concisa de abordar el problema, y ​​también maneja la puntuación/espacios en blanco al final de la cadena. – Amber

1

¿Tienes que usar expresiones regulares? ¿Sientes que debes hacerlo en una línea?

>>> import string 
>>> s = "stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD" 
>>> s2 = ''.join(c for c in s if c in string.letters + ' ') 
>>> ' '.join(s2.split()) 
'stuff morestuff stuff DD' 
3
s = "$$$aa1bb2 cc-dd ee_ff ggg." 
re.sub(r'\W+', ' ', s).upper() 
# ' AA1BB2 CC DD EE_FF GGG ' 

Es _ puntuacion?

re.sub(r'[_\W]+', ' ', s).upper() 
# ' AA1BB2 CC DD EE FF GGG ' 

¿No quieres el espacio de entrada y el de salida?

re.sub(r'[_\W]+', ' ', s).strip().upper() 
# 'AA1BB2 CC DD EE FF GGG' 
+0

+1 Para pasar por alto el paso 're.compile (...)'. Si pudiera, te daría otro +1 por señalar también la cuestión de cómo manejar '_' y WS líder/final, ya que a menudo estas cosas se pasan por alto con regex. –

1

funciona en python3 esto retendrá el mismo carácter de espacio en blanco que colapsó. Entonces, si tiene una pestaña y un espacio al lado del otro, no colapsarán en un único carácter.

def collapse_whitespace_characters(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if not cur_char.isspace() or cur_char != prev_char: 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

éste se colapsará conjuntos de espacio en blanco en el primer carácter de espacio en blanco se ve

def collapse_whitespace(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if not cur_char.isspace() or \ 
        (cur_char.isspace() and not prev_char.isspace()): 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

> > > collapse_whitespace_characters ("nosotros   como         espacios     y \ t \ t   TABS       AND   WHATEVER \ xa0 \ xa0IS ')
'nos gusta espacios y \ t TABS \ T y LO \ xa0IS'

> > > collapse_whitespace ("nosotros   como         espacios     y \ t \ t LO \   TABS       Y   xa0 \ xa0IS ')
'nos gusta espacios y \ TTabs \ T y LO \ xa0IS'

de puntuacion

def collapse_punctuation(raw_text): 
    ret = '' 
    if len(raw_text) > 1: 
     prev_char = raw_text[0] 
     ret += prev_char 
     for cur_char in raw_text[1:]: 
      if cur_char.isalnum() or cur_char != prev_char: 
       ret += cur_char 
      prev_char = cur_char 
    else: 
     ret = raw_text 
    return ret 

para responder a la pregunta en realidad

orig = 'stuff . // : /// more-stuff .. .. ...$%$% stuff -> DD' 
collapse_whitespace(''.join([(c.upper() if c.isalnum() else ' ') for c in orig])) 

como se ha dicho, la expresión regular sería algo así como

re.sub('\W+', ' ', orig).upper() 
Cuestiones relacionadas