Estoy buscando un regex
patrón que coincida con la tercera, cuarta, ... aparición de cada personaje. Mire abajo para aclaraciones:
Por ejemplo, tengo la siguiente cadena:
111aabbccxccybbzaa1
Quiero reemplazar todos los caracteres duplicados después de la segunda aparición. El resultado será:
11-aabbccx--y--z---
Algunos patrones de expresiones regulares que probé hasta ahora:
Usando la siguiente expresión regular puedo encontrar la última aparición de cada carácter: (.)(?=.*\1)
O usando este, puedo hacerlo por duplicados consecutivos pero no por duplicados: ([a-zA-Z1-9])\1{2,}
(.)(?<=^(?:(?:(?!\1).)*\1){2,}(?:(?!\1).)*\1)
expresiones regulares. Demostración .(.)(?<=(.*\1){3})
?(.)(?<=(?:.*\1){3})
también hará el trabajo, pero todo esto no es bueno ya que el retroceso excesivo puede causar problemas con cadenas más largas. Prefiero escribir un método no regex para resolver el problema.(.)(?<=(?:.*\1){3})
,(.)(?<=(?:\1.*?){2}\1)
3ms. Puedes ponerte a prueba. El tuyo parece ser el patrón menos eficiente y es el más difícil de leer.Respuestas:
Solución no regex R. Cuerda partida Reemplace los elementos de este vector que tengan rowid> = 3 * con
'-'
. Pegar de nuevo juntos.*
rowid(x)
es un vector entero con cada elemento que representa la cantidad de veces quex
se ha realizado el valor del elemento correspondiente de . Entonces, si el último elemento dex
es1
, y esa es la cuarta vez que1
ocurrex
, el último elemento derowid(x)
es4
.fuente
Puede lograr esto fácilmente sin expresiones regulares:
Ver código en uso aquí
Resultado:
Cómo funciona esto:
for u in set(s)
obtiene una lista de caracteres únicos en la cadena:{'c','a','b','y','1','z','x'}
for i in ...
recorre los índices que reunimos en 3.[i for i in range(len(s)) if s[i]==u][2:]
recorre cada carácter en la cadena y comprueba si coincideu
(desde el paso 1), luego corta la matriz desde el segundo elemento hasta el final (eliminando los dos primeros elementos si existen)s[:i]+'-'+s[i+1:]
concatenar la subcadena hasta el índice con-
y luego la subcadena después del índice, omitiendo efectivamente el carácter original.fuente
Una opción con
gsubfn
datos
fuente
No regex python one-liner:
Esto enumera a través de la cadena, contando las ocurrencias del carácter actual detrás de él y solo coloca el carácter si es uno de los primeros 2, de lo contrario, el guión.
fuente
Otra forma de hacerlo
pandas
.Salida :
fuente
Gracias a Wiktor Stribiżew , Stefan Pochmann y Bobble Bubble . En aras de la finalización, estoy publicando posibles
regex
soluciones discutidas en los comentarios;Esto solo se puede hacer con una expresión regular que admita mirar hacia atrás de ancho infinito. Usando el módulo Pyge Pyge regex podemos hacer lo siguiente:
Fragmento .
fuente