2010-11-25 8 views
6

Estoy buscando una manera eficiente de arriesgar una cadena de modo que todas las secuencias de más de 2 caracteres iguales se corten después de las primeras 2.Python: cómo cortar secuencias de más de 2 caracteres iguales en una cadena

Algunos ejemplos> insumo-producto son:

hellooooooooo -> helloo 
woooohhooooo -> woohhoo 

estoy actualmente en bucle a través de los personajes, pero es un poco lento. ¿Alguien tiene otra solución (expresión regular o algo más)

EDIT: código actual:

word_new = "" 
     for i in range(0,len(word)-2):  
      if not word[i] == word[i+1] == word[i+2]: 
       word_new = word_new+word[i] 
     for i in range(len(word)-2,len(word)): 
      word_new = word_new + word[i] 
+0

Podría publicar su código actual? – Simone

Respuesta

8

Editar: después de aplicar comentarios útiles

import re 

def ReplaceThreeOrMore(s): 
    # pattern to look for three or more repetitions of any character, including 
    # newlines. 
    pattern = re.compile(r"(.)\1{2,}", re.DOTALL) 
    return pattern.sub(r"\1\1", s) 

(respuesta original aquí) Pruebe algo como esto:

import re 

# look for a character followed by at least one repetition of itself. 
pattern = re.compile(r"(\w)\1+") 

# a function to perform the substitution we need: 
def repl(matchObj): 
    char = matchObj.group(1) 
    return "%s%s" % (char, char) 

>>> pattern.sub(repl, "Foooooooooootball") 
'Football' 
+0

Puede usar este patrón '(\ w) \ 1 {2,}' para unir solo aquellos caracteres que están en el grupo de 3 o más. Usted patrón golpea pares también. –

+0

Creo que quería decir 'pattern.sub (repl," Foooooooooootball ")' en la última línea, pero aparte de eso, ¡excelente código! – EdoDodo

+0

@Edo - gracias por la captura; corregido @ alpha-mouse - verdadero, pero efectivamente no operativo. (reemplaza un par con el mismo par) – bgporter

0

que no se sabe muy bien de expresiones regulares de Python, pero se podía adaptar éste:

s/((.)\2)\2+/$1/g; 
1

También usando una expresión regular, pero sin una función:

import re 

expr = r'(.)\1{3,}' 
replace_by = r'\1\1' 

mystr1 = 'hellooooooo' 
print re.sub(expr, replace_by, mystr1) 

mystr2 = 'woooohhooooo' 
print re.sub(expr, replace_by, mystr2) 
+0

Esto no funciona en secuencias de exactamente tres caracteres idénticos, y no ataca líneas nuevas. –

0

he puesto mi código, no es regex pero como ha mencionado "o algo más" ...

def removeD(input): 
if len(input) < 3: return input 

output = input[0:2] 
for i in range (2, len(input)): 
    if not input[i] == input[i-1] == input[i-2]: 
     output += input[i] 

return output 

no es como bgporter (¡no es broma, realmente me gusta más que la mía!) Pero, al menos en mi sistema, time informa que funciona siempre más rápido.

2

El siguiente código (a diferencia de otras respuestas basadas en expresiones regulares) hace exactamente lo que usted dice que quiere: reemplace todas las secuencias de más de 2 caracteres iguales por 2 de las mismas.

>>> import re 
>>> text = 'the numberr offf\n\n\n\ntheeee beast is 666 ...' 
>>> pattern = r'(.)\1{2,}' 
>>> repl = r'\1\1' 
>>> re.sub(pattern, repl, text, flags=re.DOTALL) 
'the numberr off\n\nthee beast is 66 ..' 
>>> 

realidad no se puede querer aplicar este tratamiento a algunos o todos los siguientes: dígitos, puntuacion, espacios, tabulaciones, saltos de línea etcccc. En ese caso, debe reemplazar el . por un subpatrón más restrictivo.

Por ejemplo:

letras ASCII: [A-Za-z]

Cualquier letra, dependiendo de la configuración regional: [^\W\d_] en conjunción con la bandera re.LOCALE

+0

Tienes razón, necesito reemplazar más que solo los caracteres ASCII. Probablemente ascii + puntuación, pero todavía no lo he decidido. Ahora sé cómo hacerlo, gracias – Bart

Cuestiones relacionadas