【问题标题】:handling hash collisions in python dictionaries处理python字典中的哈希冲突
【发布时间】:2017-06-25 10:10:39
【问题描述】:

我在 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

处理此问题的标准方法是什么?或者,我如何知道我是否应该首先担心碰撞?

【问题讨论】:

  • 嗯?您是否在实现哈希映射?

标签: python dictionary hash


【解决方案1】:

通常,您会使用用户记录中最独特的元素。这通常意味着系统通常有一个用户名或每个记录(用户)的唯一 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 可能仍然是首选方法。

【讨论】:

  • 这正好解决了我的问题。我想对记录进行哈希处理以创建密钥,即dict[hash]=record,这样当我添加新记录时,我可以使用if hash in dict 快​​速检查重复项。正如所提供的参考文献中类似描述的那样。您的建议应该对我有用,谢谢!
【解决方案2】:

使用每个字典的哈希值作为键

您没有使用字典的哈希值。字典没有哈希值。从链接来看,您似乎正在使用

hash(frozenset(my_dict.items()))

在这种情况下,您应该只是使用

frozenset(my_dict.items())

直接作为键。然后,哈希冲突将由普通的 dict 冲突处理为您处理。


一般来说,你不应该使用散列作为字典键,因为这样做会破坏冲突解决。您应该使用散列到该散列值的任何内容作为键。

【讨论】:

    【解决方案3】:

    通常,当多个键散列到同一个桶时,就会发生冲突。在这种情况下,我们需要确保我们可以区分这些键。

    Chaining collision resolution 是一种流行的技术,用于解决哈希表的冲突。例如,两个字符串“欢迎使用 stackoverflow”和“如何在 SO 中赢得声誉?”分别产生哈希码 100 和 200。假设总数组大小为 10,它们最终都在同一个存储桶中(100 % 10 和 200 % 10)。另一种方法是Open Addressing 在散列时解决冲突。

    您可以阅读Python Dictionary Implementations 上的这篇文章,其中讨论了如何处理冲突,因为 Python 字典是使用哈希表实现的。

    【讨论】:

      猜你喜欢
      • 2010-10-18
      • 1970-01-01
      • 2013-09-01
      • 2015-04-07
      • 1970-01-01
      • 2011-06-24
      • 1970-01-01
      • 2019-12-01
      • 2020-04-30
      相关资源
      最近更新 更多