में स्ट्रिंग्स का लगातार हैशिंग आप एक अनियंत्रित स्ट्रिंग को एक अद्वितीय पूर्णांक में कैसे परिवर्तित करेंगे, जो कि पाइथन सत्र और प्लेटफॉर्म पर समान होगा? उदाहरण के लिए hash('my string')
काम नहीं करेगा क्योंकि प्रत्येक पायथन सत्र और प्लेटफॉर्म के लिए एक अलग मूल्य लौटाया जाता है।पायथन
पायथन
उत्तर
यदि हैश फ़ंक्शन वास्तव में आपके लिए काम नहीं करेगा, तो आप स्ट्रिंग को एक संख्या में बदल सकते हैं।
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
यह chr
के माध्यम से एक त्रिक मैप करके, उलटी है। http://www.cse.yorku.ca/~oz/hash.html:
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'
इस तरह के MD5 या SHA1 के रूप में एक हैश एल्गोरिथ्म का उपयोग करें, तो कन्वर्ट के माध्यम से hexdigest
int()
:
>>> import hashlib
>>> int(hashlib.md5('Hello, world!').hexdigest(), 16)
144653930895353261282233826065192032313L
यह एक अच्छा जवाब है, लेकिन तकनीकी रूप पूर्णांक उत्पादित * अद्वितीय नहीं है *। उपलब्ध तारों की तुलना में कम MD5 हैश हैं। हालांकि, टकराव की संभावना बहुत कम है –
यह किसी भी हैश विधि के लिए मामला है। – MatthieuW
"बहुत कम" मतलब क्या है? विशिष्टता की आवश्यकता होने पर उत्पादन में इस एल्गोरिदम का उपयोग करना मूर्ख नहीं होगा? – kalu
सबसे पहले, आप शायद नहीं वास्तव में पूर्णांकों वास्तव में अद्वितीय होना चाहते हैं। यदि आप करते हैं तो आपकी संख्या आकार में असीमित हो सकती है। यदि वह वास्तव में वही है जो आप चाहते हैं तो आप एक बिग्नम लाइब्रेरी का उपयोग कर सकते हैं और स्ट्रिंग के बिट्स को (संभावित रूप से बहुत बड़े) पूर्णांक के प्रतिनिधित्व के रूप में समझ सकते हैं। यदि आपके तारों में \ 0 वर्ण शामिल हो सकते हैं तो आपको 1 को प्रीपेड करना चाहिए, ताकि आप उदा। "\ 0 \ 0" से "\ 0"।
अब, यदि आप बाध्य आकार संख्या पसंद करते हैं तो आप कुछ प्रकार के हैशिंग का उपयोग करेंगे। एमडी 5 काम करेगा लेकिन यह निर्दिष्ट उद्देश्य के लिए अधिक है। मैं इसके बजाय एसडीबीएम का उपयोग करने की सलाह देता हूं, यह बहुत अच्छी तरह से काम करता है। सी में यह इस तरह दिखता है:
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;
}
स्रोत, http://www.cse.yorku.ca/~oz/hash.html, यह भी कुछ अन्य हैश फंक्शन प्रस्तुत करता है।
आप काफी सही हैं। अगर मैं पूरे दस्तावेजों को एक संख्या में बदलने की कोशिश कर रहा था तो यह निश्चित रूप से एक समस्या होगी। हालांकि, मेरे आवेदन के लिए, मैं केवल छोटे तारों को परिवर्तित कर दूंगा, आमतौर पर कुछ दर्जन वर्णों से कम। – Cerin
यहाँ यहाँ सूचीबद्ध एल्गोरिदम के लिए मेरी python27 कार्यान्वयन कर रहे हैं। कोई विचार नहीं कि वे कुशल हैं या नहीं।
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)
यहां एक और विकल्प है, काफी कच्चे (शायद कई टकराव हैं) और बहुत सुगम नहीं है।
यह अलग तार के लिए एक पूर्णांक (और बाद में, एक यादृच्छिक रंग) के उद्देश्य के लिए काम किया:
aString = "don't panic"
reduce(lambda x,y:x+y, map(lambda x:ord(x[0])*x[1],zip(aString, range(1, len(aString)))))
यह मानचित्र '\ 0' और '\ 0 \ 0' एक ही चीज़ पर - आपको '1' प्रीपेड करना चाहिए। यह भी थोड़ा अक्षम है, हेक्स प्रतिनिधित्व का उपयोग कर सकता है ताकि आपके पास छोटी संख्याएं हों (यह तब स्ट्रिंग के बाइनरी प्रतिनिधित्व का उपयोग करने और इसे संख्या के रूप में व्याख्या करने के बराबर है)। – redtuna