我在哈希表中存储了数百万,可能是数十亿的4字节值,我不想存储任何密钥。我希望只需要存储键和值的哈希值。这必须很快并且都保存在RAM中。与set()不同,这些条目仍然会被密钥查找。
Python的这个实现是什么?这有名字吗?
是的,允许碰撞,可以忽略。
(我可以为碰撞做一个例外,可以存储密钥。或者,碰撞只能覆盖以前存储的值。)
答案 0 :(得分:5)
来自维基百科:
Chazelle等人。 (2004)设计了一个 Bloom过滤器的泛化 可以将值与每个值相关联 已插入的元素, 实现一个关联数组。 像Bloom过滤器一样,这些结构 通过以下方式实现小空间开销 接受虚假的小概率 阳性。在“Bloomier 过滤器“,定义了误报 当键是返回结果时 不在地图上。地图永远不会 为该键返回错误的值 在地图上。
答案 1 :(得分:3)
如何使用普通字典而不是:
d[x]=y
使用:
d[hash(x)]=y
要查找:
d[hash(foo)]
当然,如果存在哈希冲突,则可能会返回错误的值。
答案 2 :(得分:3)
它是一个很好的旧空间与运行时间的权衡:你可以拥有恒定的时间,线性空间用于hastable中的键。或者,您可以隐式存储密钥,并使用二叉树使用log n time。值的(二进制)哈希为您提供树中存储它的路径。
答案 3 :(得分:2)
在RAM中构建自己的b树。
内存使用:
(4字节)比较哈希值
(4个字节)下一个叶子的索引,如果散列< =比较或者如果是负值索引
(4字节)下一个叶子的索引,如果散列>比较OR或负值指数
b树的每个b树节点12个字节。值的开销更大(见下文)。
如何在Python中构建它 - 不存在32位整数的“本机数组”,几乎没有额外的内存开销......?他们叫什么......反正那些。
分隔有序的子数组,每个子数组包含一个或多个值。上面的“索引值”是这个大数组的索引,允许检索与哈希匹配的所有值。
这假定为32位散列。如果有,则每个b树节点需要更多字节 大于2 ^ 31-1个条目或更大的哈希。
但也许工作中的扳手:请注意,如果您没有存储键值,则无法验证查找的哈希值是否只对应于您的键,除非通过某种算法或组织机制保证没有两个键会有相同的哈希值。这里相当严重的问题。你考虑过吗? :)
答案 4 :(得分:2)
虽然python词典非常有效,但我认为如果您要存储数十亿个项目,您可能需要create您自己的C扩展,其数据结构已经过优化,你实际使用它的方式(顺序访问?完全随机?等)。
答案 5 :(得分:1)
哈希表必须存储密钥,除非你提供绝对没有冲突的哈希函数,这几乎是不可能的。
但是,如果你的键是字符串式的,那么就有一个非常节省空间的数据结构 - 有向无环字图(DAWG)。我不知道任何Python实现。
答案 6 :(得分:1)
这不是你要求购买为什么不考虑东京内阁或BerkleyDB这项工作?它不会在内存中,但是您可以通过性能来获得更大的存储容量。您仍然可以将列表保留在内存中,并仅使用数据库来检查是否存在。
答案 7 :(得分:1)
如果您实际存储了数百万个唯一值,为什么不使用字典呢?
商店:d[hash(key)/32] |= 2**(hash(key)%32)
检查:(d[hash(key)/32] | 2**(hash(key)%32))
如果您有数十亿条目,请使用大小为(2 ** 32)/ 32的numpy数组。 (因为,毕竟,你只有40亿个可能存储的值,无论如何)。
答案 8 :(得分:1)
请您告诉我们有关钥匙的更多信息?我想知道我们可以利用的密钥是否有任何规律性。
如果键是小字母表中的字符串(例如:数字字符串,如电话号码),则可以使用trie数据结构:
答案 9 :(得分:0)
为什么不是字典+ hashlib?
>>> import hashlib
>>> hashtable = {}
>>> def myHash(obj):
return hashlib.sha224(obj).hexdigest()
>>> hashtable[myHash("foo")] = 'bar'
>>> hashtable
{'0808f64e60d58979fcb676c96ec938270dea42445aeefcd3a4e6f8db': 'bar'}