2011-07-18 8 views
5

Buscando una manera rápida de limitar los duplicados a un máximo de 2 cuando se producen uno al lado del otro.Eliminar duplicados de letras que están en una fila

Por ejemplo: jeeeeeeeep =>['jep','jeep']

en busca de sugerencias en Python, pero feliz de ver un ejemplo en nada - no es difícil de cambiar.

¡Gracias por cualquier ayuda!

EDITAR: Inglés no tiene ninguna (o muchas) consonantes (misma letra) seguidas ¿no? Permite limitar esto así que no hay consonantes duplicadas en una fila y hasta dos vocales en una fila

EDIT2: Soy tonto (oye esa palabra tiene dos consonantes), simplemente revisando todas las letras, limitando las letras duplicadas que están al lado uno al otro a dos.

+0

¿En qué punto en el programa estás tratando de limitar este ? A medida que el usuario ingresa algo o después? ¿Cómo se ve la entrada? ¿Solo una palabra o una cadena completa con la posibilidad de muchas coincidencias? –

+1

¿Cuál debería ser el resultado para "jjjjeeeeppppp"? –

+0

@elmugrat - esto es básicamente ir a un corrector ortográfico, pero no está sobre la marcha, así que lo arreglaría después de presionar "enter" @Ned Ahora que lo mencionas me gustaría limitar las vocales a dos y consonantes a uno (eso es cierto para inglés, ¿no?) así que la salida todavía sería un buen punto ['jep', 'jeep'], esa especificación debía ser vista – jphenow

Respuesta

3

He aquí una solución recursiva utilizando groupby. Lo he dejado hasta que los caracteres que desea ser capaz de repetir (por defecto vocales única, aunque):

from itertools import groupby 

def find_dub_strs(mystring): 
    grp = groupby(mystring) 
    seq = [(k, len(list(g)) >= 2) for k, g in grp] 
    allowed = ('aeioupt') 
    return rec_dubz('', seq, allowed=allowed) 

def rec_dubz(prev, seq, allowed='aeiou'): 
    if not seq: 
     return [prev] 
    solutions = rec_dubz(prev + seq[0][0], seq[1:], allowed=allowed) 
    if seq[0][0] in allowed and seq[0][1]: 
     solutions += rec_dubz(prev + seq[0][0] * 2, seq[1:], allowed=allowed) 
    return solutions 

Esto es realmente sólo una forma heurística podado primero en profundidad de búsqueda en su "espacio de soluciones" de palabras posibles La heurística es que solo permitimos una sola repetición a la vez, y solo si es una carta repetible válida. Debería terminar con 2 ** n palabras al final, donde n es el número de veces que se repite un carácter "permitido" en su cadena.

>>> find_dub_strs('jeeeeeep') 
['jep', 'jeep'] 
>>> find_dub_strs('jeeeeeeppp') 
['jep', 'jepp', 'jeep', 'jeepp'] 
>>> find_dub_strs('jeeeeeeppphhhht') 
['jepht', 'jeppht', 'jeepht', 'jeeppht'] 
+0

Ver mi publicación revisada - refinado las reglas. Intenta limitar vocales a dos en una fila y no engañar en una fila de otra manera. ¿Tener sentido? – jphenow

+0

@jphenow: ¿Y qué hay de los números? Puso 1111, ¿y si el texto contiene un número que accidentalmente tiene dobles o incluso más repeticiones seguidas? Considere los números de teléfono que serían incorrectos en ese caso. – Nobody

+0

No me preocupan los números, pero redacté la afirmación sobre las consonantes, solo me preocupaban todas las letras – jphenow

-1

¡Use expresiones regulares junto con un evento de pulsación de tecla!

+1

¿Evento de pulsación de tecla? – Jacob

+1

No creo que quiera limitar la entrada de un teclado. – Nobody

0

Aquí es una solución Sh + Perl, me temo que no sé Python:

echo jjjjeeeeeeeeppppp | perl -ne 's/(.)\1+/\1\1/g; print $_;' 

La clave es la expresión regular que encuentra (.)\1+ y lo reemplaza por \1\1, a nivel mundial.

1

uso de una expresión regular:

>>> import re 
>>> re.sub(r'(.)\1\1+', r'\1\1', 'jeeeep') 
'jeep' 
1

La solución para un solo carácter utilizando groupby:

>>> from itertools import groupby 
>>> s = 'jeeeeeeeep' 
>>> ''.join(c for c, unused in groupby(s)) 
'jep' 

Y el uno para un máximo de dos personajes:

''.join(''.join(list(group)[:2]) for unused, group in groupby(s)) 
Cuestiones relacionadas