我在python中有一堆字典,每个字典都包含用户信息,例如:
NewUserDict={'name': 'John', 'age':27}
我在一个较大的字典容器中收集所有这些用户信息字典,使用每个字典的哈希值作为键(Hashing a dictionary?)。
在向字典中添加新的唯一用户时,处理哈希冲突的最佳方法是什么?我打算手动比较字典与冲突的哈希值,并只是将一些随机数添加到更新的哈希值,例如:
if new_hash in larger_dictionary:
if larger_dictionary[new_hash] != NewUserDict:
new_hash = new_hash + somerandomnumber
处理此问题的标准方法是什么?或者,我怎么知道我是否应该首先担心碰撞?
答案 0 :(得分:3)
使用每个字典的哈希值作为键
您没有使用dict的哈希值。 Dicts没有哈希值。从链接中,看起来您正在使用
hash(frozenset(my_dict.items()))
在这种情况下,您应该只使用
frozenset(my_dict.items())
直接作为关键。然后通过正常的dict碰撞处理为你处理散列碰撞。
通常,您不应该使用哈希作为dict键,因为这样做会使碰撞解决失败。您应该使用散列到该散列值的任何内容作为键。
答案 1 :(得分:3)
通常,您将使用用户记录中最独特的元素。这通常意味着系统通常具有用户名或每个记录(用户)的唯一ID,这保证是唯一的。用户名或ID将是记录的唯一键。由于这是由系统本身强制执行的,例如通过数据库表中的自动增量键,您可以确保没有冲突。
因此,唯一键应该是地图中的关键字,以便您查找用户记录。
但是,如果由于某种原因你无权访问这样一个保证是唯一的密钥,你当然可以从记录中创建一个哈希(如你所描述的)并使用任何一个哈希值用于存储可能存在碰撞键的元素的表算法。在这种情况下,你不会避免碰撞,但你只是处理它。
一种快速且常用的算法如下:在记录上使用哈希来创建密钥,就像您已经做的那样。此密钥可能不是唯一的。现在,在密钥指示的位置存储记录列表。我们将这些列表称为“桶”。要存储新元素,请对其进行哈希,然后将其附加到存储在该位置的列表中(将其添加到存储桶中)。要查找元素,请对其进行哈希处理,找到该条目,然后依次搜索该位置的列表/存储桶以查找所需的条目。
以下是一个例子:
mymap[123] = [ {'name':'John','age':27}, {'name':'Bob','age':19} ]
mymap[678] = [ {'name':'Frank','age':29} ]
在示例中,您有哈希表(通过dict实现)。您有哈希键值678,其中一个条目存储在存储桶中。然后你有哈希键值123,但是有一个冲突:'John'和'Bob'条目都有这个哈希值。无论如何,你会发现存储在mymap [123]中的存储桶并迭代它以找到值。
这是一种灵活且非常常见的哈希映射实现,不需要重新分配或其他复杂功能。它在很多地方都有描述,例如:https://www.cs.auckland.ac.nz/~jmor159/PLDS210/hash_tables.html(见第8.3.1章)。
当您遇到大量冲突时(每个存储桶的列表变得非常长),性能通常只会成为一个问题。使用良好的哈希函数可以避免的事情。
但是:例如,由数据库强制执行的记录的真正唯一ID可能仍然是首选方法。
答案 2 :(得分:1)
通常,当多个密钥散列到同一个存储桶时会发生冲突。在这种情况下,我们需要确保我们可以区分这些键。
Chaining collision resolution是用于哈希表的冲突解决的流行技术之一。例如,两个字符串“欢迎来到stackoverflow”和“如何在SO中赢得声誉?”分别产生哈希码100和200。假设总阵列大小为10,则它们最终都在同一个桶中(100%10和200%10)。另一种方法是Open Addressing,以便在散列时解决冲突。
您可以在Python Dictionary Implementations上阅读本文,其中讨论了处理冲突,因为python词典是使用哈希表实现的。