Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

106
Vistas
Reemplazar toda la cadena es más rápido que reemplazar solo su primer carácter

Traté de reemplazar un carácter a por b en una cadena grande dada. Hice un experimento: primero lo reemplacé en toda la cadena, luego lo reemplacé solo al principio.

 import re # pattern = re.compile('a') pattern = re.compile('^a') string = 'x' * 100000 pattern.sub('b', string)

Esperaba que reemplazar el principio tendría que ser mucho más rápido que reemplazar toda la cadena porque solo tiene que verificar 1 posición en lugar de 100000. Hice algunas mediciones:

 python -m timeit --setup "import re; p=re.compile('a'); string='x'*100000" "p.sub('b', string)" 10000 loops, best of 3: 19.1 usec per loop
 python -m timeit --setup "import re; p=re.compile('^a'); string='x'*100000" "p.sub('b', string)" 1000 loops, best of 3: 613 usec per loop

Los resultados muestran que, por el contrario, tratar de reemplazar toda la cadena es unas 30 veces más rápido. ¿Esperarías tal resultado? ¿Puedes explicar eso?

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Las funciones proporcionadas en el módulo Python re no se optimizan en función de los anclajes. En particular, las funciones que intentan aplicar una expresión regular en cada posición ( .search , .sub , .findall , etc.) lo harán incluso cuando la expresión regular solo pueda coincidir al principio. Es decir, incluso sin especificar el modo multilínea, de modo que ^ solo puede coincidir al principio de la cadena, la llamada no se redirige internamente. Por lo tanto:

 $ # .match only looks at the first position regardless $ python -m timeit --setup "import re; p=re.compile('a'); string='x'*100000" "p.match(string)" 2000000 loops, best of 5: 155 nsec per loop $ python -m timeit --setup "import re; p=re.compile('^a'); string='x'*100000" "p.match(string)" 2000000 loops, best of 5: 157 nsec per loop $ # .search looks at every position, even if there is an anchor $ python -m timeit --setup "import re; p=re.compile('a'); string='x'*100000" "p.search(string)" 10000 loops, best of 5: 22.4 usec per loop $ # and the anchor only adds complexity to the matching process $ python -m timeit --setup "import re; p=re.compile('^a'); string='x'*100000" "p.search(string)" 500 loops, best of 5: 746 usec per loop

Si bien re no optimiza para los anclajes, sí lo hace para varias otras cosas que podrían ocurrir al comienzo de un patrón. Una de esas optimizaciones es para un patrón que comienza con un solo carácter constante :

 if (prefix_len == 1) { /* pattern starts with a literal character */ SRE_CHAR c = (SRE_CHAR) prefix[0]; #if SIZEOF_SRE_CHAR < 4 if ((SRE_CODE) c != prefix[0]) return 0; /* literal can't match: doesn't fit in char width */ #endif end = (SRE_CHAR *)state->end; state->must_advance = 0; while (ptr < end) { while (*ptr != c) { if (++ptr >= end) return 0; } ...

Esta optimización realiza una comparación de caracteres simple para omitir las coincidencias de candidatos que no comienzan con el carácter requerido, en lugar de invocar el motor de coincidencia completo. Esta optimización es la razón por la cual la expresión regular no anclada fue mucho más rápida: hay 3 optimizaciones separadas como esta en el código, una para un solo carácter constante, otra para un prefijo constante de varios caracteres y otra para una clase de carácter, pero nada para un ^ ancla.

Creo que se puede hacer un caso razonable para presentar un informe de error en contra de esto: no tener una optimización tan obvia implementada claramente viola las expectativas. Aparte de eso, si bien es fácil reemplazar .search con un ancla usando .match , no es tan sencillo reemplazar .sub con un ancla: debe .match , verificar el resultado y luego llamar a .replace en la cadena usted mismo.

Si necesita anclar al final de la cuerda y no al principio, se vuelve mucho más difícil; Recuerdo el antiguo consejo de Perl de intentar invertir la cadena primero, pero en general es difícil escribir un patrón que coincida con el reverso de lo que quieres.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda