Cualquier número finito de dígitos resultará en colisiones para un número suficientemente grande de elementos hash, por eso no debe tratarlos como claves únicas; tiende a convertirse en el problema del cumpleaños.
Alex North-Keys
1
Elegí "CityHash" para codificar cadenas de números enteros de 19 dígitos (enteros de 64 bits), con la esperanza de que esto conduzca a menos colisiones potenciales que la sugerencia de Raymond a continuación. en.wikipedia.org/wiki/List_of_hash_functions
tryptofame
Respuestas:
154
Sí, puede utilizar los módulos hashlib incorporados o la función hash incorporada. Luego, corte los últimos ocho dígitos usando operaciones de módulo o operaciones de corte de cadenas en la forma entera del hash:
>>> s ='she sells sea shells by the sea shore'>>># Use hashlib>>>import hashlib
>>> int(hashlib.sha1(s).hexdigest(),16)%(10**8)58097614L>>># Use hash()>>> abs(hash(s))%(10**8)82148974
anuncio de servicio público ... esta técnica en realidad no da como resultado un valor hash único para la cadena; calcula un hash y luego se convierte en un valor único no garantizado
twneale
88
anuncio de servicio público ... excepto en el caso especial de hashes perfectos sobre un conjunto limitado de valores de entrada, no se supone que las funciones hash generen valores únicos garantizados.
Raymond Hettinger
5
¿Leíste la pregunta del OP? Él (o ella) quería (o necesitaba) 8 lugares decimales. Además, la forma en que funcionan las tablas hash es en un pequeño espacio de búsqueda (la tabla dispersa). Parece que no sabe que las funciones de hash de búsqueda se usan comúnmente y que no le importa la pregunta real que se hizo.
Raymond Hettinger
17
Leí la pregunta. Simplemente estoy observando que en el mismo espacio de entrada que SHA-1, su respuesta es astronómicamente más probable que produzca una colisión que no. La pregunta requiere implícitamente al menos cierto grado de unicidad, pero su respuesta es una función hash con el mismo espíritu que una que simplemente devuelve 12345678 para cada entrada. Pude generar experimentalmente una colisión con tan solo 1000 entradas usando este método. Para conservar la misma probabilidad de colisión que SHA-1, tendría que asignar SHA-1 no truncados a números enteros de 8 dígitos. Creo que es digno de un
anuncio de servicio público
20
Cuidado, no se garantiza que los hash (s) den los mismos resultados en todas las plataformas y ejecuciones.
Sr. Napik
94
La respuesta de Raymond es excelente para python2 (sin embargo, no necesita el abs () ni el parens alrededor de 10 ** 8). Sin embargo, para python3, existen importantes advertencias. Primero, deberá asegurarse de pasar una cadena codificada. En estos días, en la mayoría de las circunstancias, probablemente también sea mejor evitar sha-1 y usar algo como sha-256 en su lugar. Entonces, el enfoque de hashlib sería:
>>>import hashlib
>>> s ='your string'>>> int(hashlib.sha256(s.encode('utf-8')).hexdigest(),16)%10**880262417
Si desea utilizar la función hash () en su lugar, la advertencia importante es que, a diferencia de Python 2.x, en Python 3.x, el resultado de hash () solo será coherente dentro de un proceso, no entre las invocaciones de Python. Mira aquí:
Cabe señalar que esta respuesta tiene una advertencia muy importante desde Python 3.3, para protegerse contra Python 3.3 y versiones posteriores, use una semilla hash aleatoria al inicio.
Wolph
Si los dígitos no son su requisito principal, también puede usar la hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]bruja todavía tendrá colisiones
lony
¡Deberían poner eso en la caja!
Tomasz
3
Solo para completar la respuesta de JJC, en Python 3.5.3 el comportamiento es correcto si usa hashlib de esta manera:
Estoy compartiendo nuestra implementación de nodejs de la solución implementada por @Raymond Hettinger.
var crypto = require('crypto');
var s ='she sells sea shells by the sea shore';
console.log(BigInt('0x'+ crypto.createHash('sha1').update(s).digest('hex'))%(10n**8n));
¿Estás compartiendo una solución de nodejs en una pregunta sobre Python?
Harabeck
Sí, cuando estábamos construyendo el sistema, el backend procesó esto usando python mientras que el frontend usó node.js. Necesario para asegurarse de que ambos funcionen a la perfección.
Respuestas:
Sí, puede utilizar los módulos hashlib incorporados o la función hash incorporada. Luego, corte los últimos ocho dígitos usando operaciones de módulo o operaciones de corte de cadenas en la forma entera del hash:
fuente
La respuesta de Raymond es excelente para python2 (sin embargo, no necesita el abs () ni el parens alrededor de 10 ** 8). Sin embargo, para python3, existen importantes advertencias. Primero, deberá asegurarse de pasar una cadena codificada. En estos días, en la mayoría de las circunstancias, probablemente también sea mejor evitar sha-1 y usar algo como sha-256 en su lugar. Entonces, el enfoque de hashlib sería:
Si desea utilizar la función hash () en su lugar, la advertencia importante es que, a diferencia de Python 2.x, en Python 3.x, el resultado de hash () solo será coherente dentro de un proceso, no entre las invocaciones de Python. Mira aquí:
Esto significa la solución basada en hash () sugerida, que se puede acortar a solo:
hash(s) % 10**8
solo devolverá el mismo valor dentro de una ejecución de script determinada:
Entonces, dependiendo de si esto es importante en su aplicación (lo hizo en la mía), probablemente querrá ceñirse al enfoque basado en hashlib.
fuente
hashlib.sha256("hello world".encode('utf-8')).hexdigest()[:8]
bruja todavía tendrá colisionesSolo para completar la respuesta de JJC, en Python 3.5.3 el comportamiento es correcto si usa hashlib de esta manera:
fuente
Estoy compartiendo nuestra implementación de nodejs de la solución implementada por @Raymond Hettinger.
fuente