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()