Wie würden Sie eine beliebige Zeichenfolge in eine eindeutige Ganzzahl konvertieren, die in Python-Sitzungen und -Plattformen identisch ist? Beispielsweise würde hash('my string')
nicht funktionieren, da für jede Python-Sitzung und -Plattform ein anderer Wert zurückgegeben wird.Persistentes Hashing von Strings in Python
Antwort
Wenn eine Hash-Funktion wirklich nicht funktioniert, können Sie die Zeichenfolge in eine Zahl umwandeln.
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
Dies ist umkehrbar, indem jedes Triplett durch chr
abbildet.
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'
einen Hash-Algorithmus wie MD5 oder SHA1 verwenden, dann wandeln die hexdigest
über int()
:
>>> import hashlib
>>> int(hashlib.md5('Hello, world!').hexdigest(), 16)
144653930895353261282233826065192032313L
Dies ist eine gute Antwort, aber technisch die erzeugte ganze Zahl ist nicht * einzigartig *. Es gibt weniger MD5-Hashes als verfügbare Strings. Die Wahrscheinlichkeit einer Kollision ist jedoch sehr gering –
Dies ist der Fall für jede Hash-Methode. – MatthieuW
Was bedeutet "sehr niedrig"? Wäre es unklug, diesen Algorithmus in der Produktion zu verwenden, wenn Eindeutigkeit erforderlich ist? – kalu
First off, haben Sie wahrscheinlich nicht wirklich die ganzen Zahlen tatsächlich einzigartig sein wollen. Wenn Sie das tun, sind Ihre Nummern möglicherweise nicht unbegrenzt groß. Wenn das wirklich das ist, was Sie wollen, dann könnten Sie eine Bibliothek bignum verwenden und die Bits der Zeichenkette als Darstellung einer (möglicherweise sehr großen) Ganzzahl interpretieren. Wenn Ihre Zeichenfolgen das Zeichen \ 0 enthalten können, sollten Sie eine 1 voranstellen, damit Sie z. "\ 0 \ 0" von "\ 0".
Wenn Sie jetzt Zahlen in begrenzter Größe bevorzugen, verwenden Sie eine Art von Hashing. MD5 wird funktionieren, aber es ist Overkill für den angegebenen Zweck. Ich empfehle stattdessen, sdbm zu verwenden, es funktioniert sehr gut. In C sieht es wie folgt aus:
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;
}
Die Quelle, http://www.cse.yorku.ca/~oz/hash.html stellt auch ein paar andere Hash-Funktionen.
Sie sind ziemlich richtig. Dies wäre definitiv ein Problem, wenn ich ganze Dokumente in eine Nummer konvertieren wollte. Für meine Anwendung konvertiere ich jedoch nur kurze Zeichenfolgen, normalerweise weniger als ein paar Dutzend Zeichen. – Cerin
Hier sind meine python27 Implementierung für Algorithmen hier aufgelistet: http://www.cse.yorku.ca/~oz/hash.html. Keine Ahnung, ob sie effizient sind oder nicht.
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)
Hier ist eine andere Option, ziemlich roh (wahrscheinlich hat viele Kollisionen) und nicht sehr gut lesbar.
Er arbeitete für den Zweck einen int zu generieren (und später, eine zufällige Farbe) für verschiedene Strings:
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. Hashing (Verbergen) Strings in Python
- 2. Persistentes Python-Befehlszeilenprotokoll
- 3. läuft ein persistentes Python-Skript von Systemd?
- 4. deterministischer Hashing in Python 3
- 5. Vectorizing-Funktion Hashing in Python
- 6. Verwendet Python-Memcache konsistentes Hashing?
- 7. Formatieren von Strings in Python
- 8. Hmac Hashing Fehler in Python 3.5
- 9. Python-Daten persistentes Objekt für die Kommunikation zwischen Threads
- 10. Persistentes lokales JavaScript - Chrome Debugger
- 11. Hashing von Hashtable verwendet?
- 12. Splitting-Strings in Python
- 13. Strings in Python listet
- 14. Python: Vergleich von zwei Strings
- 15. Unescence Python Strings von HTTP
- 16. Vergleichen von komplexen JSON-Strings in Python
- 17. Spalte mit Liste von Strings in Python
- 18. Hervorhebung von SQL in Python Strings
- 19. Berechne SHA1 von Strings in Python
- 20. Python tkinter Passwort Checker GUI - Hashing Problem
- 21. Python: Strings in eine Liste
- 22. Kuckuck Hashing in C
- 23. 'C-Stil' Strings in Python
- 24. Konvertieren von Listen von Tupeln Python Strings
- 25. Python-Wörterbuch, das Strings einer Gruppe von Strings zuordnet?
- 26. Hashing verschiedene Tupel in Python geben identische Ergebnis
- 27. Hashing in ms Zugriff
- 28. mit Salzen in Hashing
- 29. DCPcrypt Hashing deutsche Umlaute
- 30. Zeit in Strings Format: Python
Dies bildet '\ 0' und '\ 0 \ 0' auf dasselbe ab - Sie sollten eine '1' voranstellen. Auch dies ist ein wenig ineffizient, könnte die hexadezimale Darstellung verwenden, so dass Sie kleinere Zahlen hätten (das entspricht dann der Verwendung der binären Darstellung der Zeichenfolge und interpretieren sie als eine Zahl). – redtuna