首页 > 解决方案 > JavaScript 是否将哈希表用于 Map 和 Set?

问题描述

我是一名 Python 开发人员,在 JavaScript 中迈出了第一步。

我开始使用MapSet。它们似乎具有与dictPython相同的 API set,所以我假设它们是一个哈希表,我可以依靠 O(1) 查找时间。

但后来,出于好奇,我试图看看如果我在 Chrome 的控制台中执行此操作会发生什么:

new Set([new Set([1, 2, 3])])

会发生什么:

Set(1) {Set(3)}

JavaScript 愉快地创建了集合。怎么会这样?在 Python 中你会得到一个错误,因为你不能把一个可变项放在一个集合或一个字典中。为什么 JavaScript 允许它?

标签: javascriptpythondictionarysethashtable

解决方案


考虑以下 JS 代码:

> m1 = new Map([['a', 1]])
Map { 'a' => 1 }
> m2 = new Map()
Map {}
> m2.set(m1, 3)
Map { Map { 'a' => 1 } => 3 }
> m2.get(m1)
3

但请注意,它是基于身份的散列,即===,所以......

> m2.get(new Map([['a',1]]))
undefined

所以说真的,这张地图有多大用处?

请注意,这与 Python 的默认行为没有什么不同。用户定义类型的默认状态是可散列:

>>> class Foo: pass
...
>>> f0 = Foo()
>>> s = {f0}
>>> Foo() in s
False
>>> f0 in s
True

在 Python 中,默认情况下object.__eq__会根据身份进行比较,所以上面的就可以了。但是,如果您 override __eq__,默认情况下,__hash__设置为None并尝试使用基于散列的容器将失败:

>>> class Bar:
...    def __init__(self, value):
...       self.value = value
...    def __eq__(self, other):
...       return self.value == other.value
...
>>> b0 = Bar(0)
>>> b1 = Bar(2)
>>> {b0, b1}
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'Bar'

在这一点上,您必须实现__hash____eq__


推荐阅读