python - 散列函数问题 : hash(1) == hash(1. 0)

标签 python hash dictionary

我有一个 dict 实例,其中 intfloatstring 作为键,但是问题是当 aintbfloatfloat(a) == b,那么它们的哈希值是相同的,这就是我不想得到的,因为在这种情况下我需要唯一的哈希值才能获得相应的值。

例子:

d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0}
d[1] == '1.0'
d[1.0] == '1.0'
d['1'] == 1
d['1.0'] == 1.0

我需要的是:

d = {1:'1', 1.0:'1.0', '1':1, '1.0':1.0}
d[1] == '1'
d[1.0] == '1.0'
d['1'] == 1
d['1.0'] == 1.0

最佳答案

1 == 1.0 以来,如果 hash(1) != hash(1.0) 会严重破坏散列的语义(因此也破坏了字典和集合) 。更一般地说,对于所有 xx == y 必须始终是 hash(x) == hash(y)y(当然没有条件要求反向蕴涵成立)。

因此您的字典 d 只有三个条目,因为您在字典显示中写入的第二个条目会覆盖第一个条目。如果你需要强制只在相同类型之间保持相等(而不是更普遍的数字),你需要一个包装器,例如:

class W(object):

  def __init__(self, x):
    self.x = x
    self.t = type(x)

  def __eq__(self, other):
    t = type(other)
    if t != type(self):
      return False
    return self.x == other.x and self.t == other.t

  def __hash__(self):
    return hash(self.x) ^ hash(self.t)

  def __getattr__(self, name):
    return getattr(self.x, name)

根据您的具体需要,您可能还想覆盖其他方法(其他比较方法,例如 __cmp____le__,算术方法,__repr__ 等)。无论如何,这将允许您构建一个类似于您需要的字典,只需使用 W(1) 而不是裸露的 1W( 1.0) 而不是裸露的 1.0 (您可能不需要包装非数字,尽管如果您选择这样做也没有坏处,并且如果所有键都可以简化从字典中的检索同样包裹)。

关于python - 散列函数问题 : hash(1) == hash(1. 0),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1228475/

相关文章:

java - 重新哈希方法抛出 NullPointerException

python - 如何通过函数将字典中的多个键与一个值配对?

java - 用于在 Java 中创建通用哈希表的哈希函数(用于学习目的)

python - 使用 python并发.futures 提交进程编号

python - 更改一个列表也会意外地更改另一个列表

python - wave.error : # channels not specified 错误

ruby-on-rails - 升级到 Rails 5 时,序列化为哈希的现有数据会产生错误

C++ STL 错误的键类型

python - 从字典创建类实例?

python - key :Value Pairs from txt file into a dictionary