tengo una cadena como
aaabbbbccaY me gustaría analizar todas las subcadenas uniformes posibles a partir de eso. Entonces mis subcadenas esperadas para esta cadena son
['a', 'aa', 'aaa', 'b', 'bb', 'bbb', 'bbbb', 'c', 'cc', 'a']Intenté lo siguiente
import re print(re.findall(r"([az])(?=\1*)", "aaabbbbcca")) # Output: ['a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'a']¿Es posible a través de expresiones regulares? ¿Si es así, entonces cómo?
Puede lograr lo que necesita sin una expresión regular aquí:
result = [] text = "aaabbbbcca" prev = '' for c in text: if c == prev: result.append(result[-1] + c) else: result.append(c) prev = c print(result) # => ['a', 'aa', 'aaa', 'b', 'bb', 'bbb', 'bbbb', 'c', 'cc', 'a']Vea la demostración de Python .
En resumen, puede iterar sobre la cadena y agregar un nuevo elemento a una lista de result cuando el nuevo carácter no es igual al carácter anterior; de lo contrario, puede agregar un nuevo elemento con el valor igual al elemento anterior + el mismo carácter concatenado al valor.
Con expresiones regulares , lo mejor que puedes hacer es
import re text = "aaabbbbcca" print( [x.group(1) for x in re.finditer(r'(?=((.)\2*))', text)] ) # => ['aaa', 'aa', 'a', 'bbbb', 'bbb', 'bb', 'b', 'cc', 'c', 'a'] Vea esta demostración de Python . Aquí, (?=((.)\2*)) coincide con cualquier ubicación dentro de la cadena inmediatamente precedida por cualquier carácter (aparte de los caracteres de salto de línea si no usa la opción re.DOTALL ) seguido por cero o más apariciones del mismo carácter (capturando los caracteres en el Grupo 1).
Creo que este problema en particular se puede resolver con una expresión regular. La respuesta se basa en esta respuesta, donde se extraen partes de números. La explicación es la misma que en la otra respuesta. Cada coincidencia crea un grupo vacío y un grupo dentro de la anticipación. La búsqueda anticipada captura secuencias de a , b o c de al menos una longitud de 1. Luego, simplemente creamos una lista de cadenas que están en el segundo grupo.
import re s = "aaabbbbcca" matches = re.finditer(r'(?=(a{1,}|b{1,}|c{1,}))',s) results = [match.group(1) for match in matches] print(results)Producción:
['aaa', 'aa', 'a', 'bbbb', 'bbb', 'bb', 'b', 'cc', 'c', 'a']Los valores de la salida son los mismos que los solicitados, pero no exactamente en el mismo orden.
Puede usar una expresión regular para encontrar rayas del mismo carácter, y luego algo de Python en la parte superior para construir las rayas más pequeñas.
import re s = 'aaabbbbcca' matches = (m.group() for m in re.finditer(r'([az])\1*', s)) result = [m[:i] for m in matches for i in range(1, len(m) + 1)] También hay una solución itertools .
from itertools import groupby s = 'aaabbbbcca' matches = (''.join(g) for _, g in groupby(s)) result = [m[:i] for m in matches for i in range(1, len(m) + 1)]Usando dos funciones itertools :
from itertools import groupby, accumulate s = 'aaabbbbcca' print([a for _, g in groupby(s) for a in accumulate(g)])O simplemente con lo básico:
s = 'aaabbbbcca' a = '' print([a := a * (c in a) + c for c in s])Salida para ambos:
['a', 'aa', 'aaa', 'b', 'bb', 'bbb', 'bbbb', 'c', 'cc', 'a']