Comment convertir une chaîne arbitraire en un entier unique, ce qui serait le même pour les sessions et plates-formes Python? Par exemple hash('my string')
ne fonctionnerait pas car une valeur différente est renvoyée pour chaque session et plate-forme Python.Hashing persistant de chaînes en Python
Répondre
Si une fonction de hachage ne fonctionne vraiment pas pour vous, vous pouvez transformer la chaîne en un nombre.
my_string = 'my string'
def string_to_int(s):
ord3 = lambda x : '%.3d' % ord(x)
return int(''.join(map(ord3, s)))
In[10]: string_to_int(my_string)
Out[11]: 109121032115116114105110103L
Ceci est inversible, en mappant chaque triplet par chr
.
def int_to_string(n)
s = str(n)
return ''.join([chr(int(s[i:i+3])) for i in range(0, len(s), 3)])
In[12]: int_to_string(109121032115116114105110103L)
Out[13]: 'my string'
utiliser un algorithme de hachage telle que MD5 ou SHA1, puis convertir le hexdigest
via int()
:
>>> import hashlib
>>> int(hashlib.md5('Hello, world!').hexdigest(), 16)
144653930895353261282233826065192032313L
C'est une bonne réponse, mais techniquement l'entier produit n'est pas * * unique. Il y a moins de hachages MD5 que de chaînes disponibles. Cependant, les chances d'une collision sont très faibles –
C'est le cas pour toute méthode de hachage. – MatthieuW
Que signifie "très faible"? Serait-il imprudent d'utiliser cet algorithme en production lorsque l'unicité est requise? – kalu
Tout d'abord, vous ne probablement pas vraiment veulent les entiers pour être réellement unique. Si vous le faites, vos numéros pourraient être illimités. Si c'est vraiment ce que vous voulez, vous pouvez utiliser une bibliothèque bignum et interpréter les bits de la chaîne comme la représentation d'un entier (potentiellement très grand). Si vos chaînes peuvent inclure le caractère \ 0, vous devez ajouter un 1, ce qui vous permet de distinguer, par exemple, "\ 0 \ 0" à partir de "\ 0". Maintenant, si vous préférez des nombres de taille bornée, vous utiliserez une forme de hachage. MD5 fonctionnera mais c'est exagéré pour l'objectif annoncé. Je recommande d'utiliser sdbm à la place, cela fonctionne très bien. En C, il ressemble à ceci:
static unsigned long sdbm(unsigned char *str)
{
unsigned long hash = 0;
int c;
while (c = *str++)
hash = c + (hash << 6) + (hash << 16) - hash;
return hash;
}
La source, http://www.cse.yorku.ca/~oz/hash.html, présente également quelques autres fonctions de hachage.
Vous avez tout à fait raison. Ce serait certainement un problème si j'essayais de convertir des documents entiers en nombre. Cependant, pour mon application, je ne convertirai que des chaînes courtes, généralement moins de quelques dizaines de caractères. – Cerin
Voici mon implémentation de python27 pour les algorithmes listés ici: http://www.cse.yorku.ca/~oz/hash.html. Aucune idée si elles sont efficaces ou non.
from ctypes import c_ulong
def ulong(i): return c_ulong(i).value # numpy would be better if available
def djb2(L):
"""
h = 5381
for c in L:
h = ((h << 5) + h) + ord(c) # h * 33 + c
return h
"""
return reduce(lambda h,c: ord(c) + ((h << 5) + h), L, 5381)
def djb2_l(L):
return reduce(lambda h,c: ulong(ord(c) + ((h << 5) + h)), L, 5381)
def sdbm(L):
"""
h = 0
for c in L:
h = ord(c) + (h << 6) + (h << 16) - h
return h
"""
return reduce(lambda h,c: ord(c) + (h << 6) + (h << 16) - h, L, 0)
def sdbm_l(L):
return reduce(lambda h,c: ulong(ord(c) + (h << 6) + (h << 16) - h), L, 0)
def loselose(L):
"""
h = 0
for c in L:
h += ord(c);
return h
"""
return sum(ord(c) for c in L)
def loselose_l(L):
return reduce(lambda h,c: ulong(ord(c) + h), L, 0)
Voici une autre option, assez grossière (qui a probablement beaucoup de collisions) et qui n'est pas très lisible.
Il a travaillé dans le but de générer un int (et plus tard, une couleur aléatoire) pour les chaînes différentes:
aString = "don't panic"
reduce(lambda x,y:x+y, map(lambda x:ord(x[0])*x[1],zip(aString, range(1, len(aString)))))
- 1. Persistant valeur variable Python
- 2. Problème persistant des longues chaînes avec Hibernate
- 3. Historique de ligne de commande Python persistant
- 4. manipulation de chaînes en Python
- 5. Hashing mots de passe utilisateur
- 6. Hashing cohérent avec memcache
- 7. Hashing mots de passe tomcat
- 8. Chaînes 'style C' en Python
- 9. Problème de correspondance de chaînes en Python
- 10. Comment créer un serveur COM persistant en Python
- 11. Division de chaînes Python
- 12. Substitution de chaînes python
- 13. manipulation de chaînes en Python docstrings
- 14. Créer des variables de chaînes en Python
- 15. Hashing Credentials dans Objective C
- 16. Comparaison de chaînes Python
- 17. .NET 3.5 - Hashing un mot de passe en utilisant System.Cryptography
- 18. Python - convertir des chaînes de caractères larges d'un fichier binaire en chaînes unicode Python
- 19. Conversion de séries de chaînes en liste flottante en python
- 20. Lire des chaînes Unicode "crues" en Python
- 21. Décodage chaînes codées html en python
- 22. trouver des sous-chaînes en python
- 23. Python joignant des chaînes
- 24. groupements de chaînes Parsing (Python)
- 25. python: comparaison de deux chaînes
- 26. Mettre en forme des nombres en chaînes en Python
- 27. Meilleure façon de randomiser une liste de chaînes en Python
- 28. Lecture de fichiers dans la liste de chaînes en Python
- 29. Comment rendre persistant un dictionnaire python sur google appengine
- 30. Ecriture de chaînes Unicode via sys.stdout en Python
Ceci met en correspondance '\ 0' et '\ 0 \ 0' avec la même chose - vous devez ajouter un '1'. De plus, c'est un peu inefficace, vous pouvez utiliser la représentation hexadécimale pour avoir des nombres plus petits (cela équivaut alors à utiliser la représentation binaire de la chaîne et à l'interpréter comme un nombre). – redtuna