Saltar al contenido

Python suma de valores ASCII de todos los caracteres en un string

Luego de mucho luchar ya encontramos el resultado de esta impedimento que ciertos de nuestros lectores de este espacio han tenido. Si deseas compartir algo puedes compartir tu conocimiento.

Solución:

Puedes usar un intermedio bytearray para acelerar las cosas:

>>> sum(bytearray("abcdefgh"))
804

Esto no es 17 veces más rápido que el generador: implica la creación de un intermediario bytearray y sum todavía tiene que iterar sobre objetos enteros de Python, pero en mi máquina acelera la suma de un número de 8 caracteres string desde 2μs hasta alrededor de 700ns. Si un tiempo en este estadio sigue siendo demasiado ineficiente para su caso de uso, probablemente debería escribir las partes críticas de velocidad de su aplicación en C de todos modos.

Si sus cadenas son lo suficientemente grandes, y si puede usar numpypuede evitar la creación de copias temporales consultando directamente el stringel búfer usando numpy.frombuffer:

>>> import numpy as np
>>> np.frombuffer("abcdefgh", "uint8").sum()
804

Para cadenas más pequeñas, esto es más lento que un temporal array debido a las complejidades en la maquinaria de creación de vistas de numpy. Sin embargo, para cadenas lo suficientemente grandes, la frombuffer El enfoque comienza a dar sus frutos y, por supuesto, siempre genera menos basura. En mi máquina, el punto de corte es string tamaño de unos 200 caracteres.

Además, vea el ensayo clásico de Guido Anécdota de optimización de Python. Si bien algunas de sus técnicas específicas pueden ser obsoletas ahora, la lección general de cómo pensar sobre la optimización de Python sigue siendo bastante relevante.


Puede cronometrar los diferentes enfoques con el timeit módulo:

$ python -m timeit -s 's = "a" * 20' 'sum(ord(ch) for ch in s)' 
100000 loops, best of 3: 3.85 usec per loop
$ python -m timeit -s 's = "a" * 20' 'sum(bytearray(s))'
1000000 loops, best of 3: 1.05 usec per loop
$ python -m timeit -s 'from numpy import frombuffer; s = "a" * 20' 
                      'frombuffer(s, "uint8").sum()' 
100000 loops, best of 3: 4.8 usec per loop

Puede acelerarlo un poco (~ 40% ish, pero no tan rápido como C nativo) eliminando la creación del generador …

En vez de:

sum(ord(c) for c in string)

Hacer:

sum(map(ord, string))

Horarios:

>>> timeit.timeit(stmt="sum(map(ord, 'abcdefgh'))")
# TP: 1.5709713941578798
# JC: 1.425781011581421
>>> timeit.timeit(stmt="sum(ord(c) for c in 'abcdefgh')")
# TP: 1.7807035140629637
# JC: 1.9981679916381836

print sum(map(ord,my_string))

Esto sería lo más fácil.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *