saber minusculas minuscula metodo mayusculas mayuscula lower funciones español determinar convertir contar cadena python string performance case-insensitive startswith

minusculas - metodo capitalize python



Inicio de cadena insensible a mayúsculas y minúsculas en Python (4)

Así es como compruebo si mystring comienza con alguna cadena:

>>> mystring.lower().startswith("he") True

El problema es que mystring es muy largo (miles de caracteres), por lo que la operación lower() lleva mucho tiempo.

PREGUNTA: ¿Hay una manera más eficiente?

Mi intento fallido:

>>> import re; >>> mystring.startswith("he", re.I) False


Dependiendo del rendimiento de .lower (), si el prefijo era lo suficientemente pequeño, podría ser más rápido verificar la igualdad varias veces:

s = ''A'' * 2000 prefix = ''he'' ch0 = s[0] ch1 = s[1] substr = ch0 == ''h'' or ch0 == ''H'' and ch1 == ''e'' or ch1 == ''E''

Timing (usando la misma cadena que NPE):

>>> timeit.timeit("ch0 = s[0]; ch1 = s[1]; ch0 == ''h'' or ch0 == ''H'' and ch1 == ''e'' or ch1 == ''E''", "s = ''A'' * 2000") 0.2509511683747405 = 0.25 us per loop

Comparado con el método existente:

>>> timeit.timeit("s.lower().startswith(''he'')", "s = ''A'' * 2000", number=10000) 0.6162763703208611 = 61.63 us per loop

(Esto es horrible, por supuesto, pero si el código es extremadamente crítico para el rendimiento, puede valer la pena)


Ninguna de las respuestas dadas es correcta, tan pronto como considere algo fuera del rango ASCII.

Por ejemplo, en una comparación insensible a un caso, ß debe considerarse igual a SS si está siguiendo las reglas de mapeo de casos de Unicode.

Para obtener resultados correctos, la solución más fácil es instalar el módulo de regex de Python que sigue el estándar:

import re import regex # enable new improved engine instead of backwards compatible v0 regex.DEFAULT_VERSION = regex.VERSION1 print(re.match(''ß'', ''SS'', re.IGNORECASE)) # none print(regex.match(''ß'', ''SS'', regex.IGNORECASE)) # matches


Puede usar una expresión regular de la siguiente manera:

In [33]: bool(re.match(''he'', ''Hello'', re.I)) Out[33]: True In [34]: bool(re.match(''el'', ''Hello'', re.I)) Out[34]: False

En una cadena de 2000 caracteres, esta es aproximadamente 20 veces más rápida que la lower() :

In [38]: s = ''A'' * 2000 In [39]: %timeit s.lower().startswith(''he'') 10000 loops, best of 3: 41.3 us per loop In [40]: %timeit bool(re.match(''el'', s, re.I)) 100000 loops, best of 3: 2.06 us per loop

Si está haciendo coincidir el mismo prefijo en varias ocasiones, la precompresión de la expresión regular puede marcar una gran diferencia:

In [41]: p = re.compile(''he'', re.I) In [42]: %timeit p.match(s) 1000000 loops, best of 3: 351 ns per loop

Para prefijos cortos, cortar el prefijo de la cadena antes de convertirlo a minúsculas podría ser incluso más rápido:

In [43]: %timeit s[:2].lower() == ''he'' 1000000 loops, best of 3: 287 ns per loop

Los tiempos relativos de estos enfoques dependerán, por supuesto, de la longitud del prefijo. En mi máquina, el punto de equilibrio parece ser de unos seis caracteres, que es cuando la expresión regular precompilada se convierte en el método más rápido.

En mis experimentos, verificar cada personaje por separado podría ser incluso más rápido:

In [44]: %timeit (s[0] == ''h'' or s[0] == ''H'') and (s[1] == ''e'' or s[1] == ''E'') 1000000 loops, best of 3: 189 ns per loop

Sin embargo, este método solo funciona para los prefijos que se conocen cuando se escribe el código, y no se presta a prefijos más largos.


Qué tal esto:

prefix = ''he'' if myVeryLongStr[:len(prefix)].lower() == prefix.lower()