对于某些应用程序,我需要为一大组标记中的每个字符串标记创建一个唯一整数键的函数,这样该哈希值将成为哈希列表中的索引。
其中一个问题是在典型的散列函数中它可以得到负值,所以我把它变为2的幂,然后我得到除以列表大小的余数,以便索引总是在列表大小。
另一个最严重的问题是我可以获得具有相同哈希值的多个令牌。有没有办法为每个标记创建一个唯一的哈希值,比如基于字符的ord(),结合长度......等,以避免多个标记具有相同的哈希值?
import urllib2,re
size=10**9 #size of hash list
hash_list=[None]*size
text = urllib2.urlopen('http://www.gutenberg.org/files/972/972.txt').read()
tokens=[v.lower() for v in re.split('\W+',text) if v]
for t in tokens:
index=hash(t)**2 % size
if hash_list[index]==None:
hash_list[index]=t
elif hash_list[index]<>None and hash_list[index]<>t:
print hash_list[index],t
答案 0 :(得分:1)
如果确实想要使用散列,abs(hash(t))
比hash(t)**2
更好(也更快):你仍然将负片折叠到正面,但结果永远是int
,而平方通常会给你一个long
。
(请记住,如果有必要,Python会自动将int
表达式的结果提升为long
,但它不会自动将小long
降级为int
{1}})。
此外,平方使得分布不均匀,因此增加了碰撞的机会。但是你不需要做平方或abs()
来摆脱否定:无论如何,%
运算符都会这样做。 OTOH,如果你使表格大小为二进制幂,你可以使用>>
而不是%
,并且比特移位不会像任意数字的模数一样扭曲分布。
Python hash()
非常好,但您可能希望在应用hash()
之前尝试使用其他散列函数来随机化您的令牌,例如sha()
函数系列之一或md5()
,可以在hashlib中找到。
答案 1 :(得分:0)
不要自己实施;使用set
。
import urllib2,re
text = urllib2.urlopen('http://www.gutenberg.org/files/972/972.txt').read()
unique_tokens = set(v.lower() for v in re.split('\W+',text) if v)