python - 类的两个实例相等但哈希码不同
问题描述
我正在研究空间项目中的几何,我有不同的几何实体,其中 Point. 有时两个点相等,但由于计算导致的小数值误差,例如 1 和 1.0000000001,所以我实现了__eq__
带有math.isclose()
函数的方法来解决这个问题。
class Point(object):
def __init__(self, x, y, z):
self.x = x
self.y = y
self.z = z
def __eq__(self, other):
if isinstance(other, Point):
equal_x = math.isclose(other.x, self.x, rel_tol=5e-3, abs_tol=1e-5)
equal_y = math.isclose(other.y, self.y, rel_tol=5e-3, abs_tol=1e-5)
equal_z = math.isclose(other.z, self.z, rel_tol=5e-3, abs_tol=1e-5)
if equal_x and equal_y and equal_z:
return True
return False
在使用集合和字典时,如何实现该__hash__
方法以使这两个对象相等?
最终目标是使用以下函数来“唯一化”此类对象的列表并删除重复项:
def f12(seq):
# from Raymond Hettinger
# https://twitter.com/raymondh/status/944125570534621185
return list(dict.fromkeys(seq))
解决方案
您的 equal 方法存在一般问题。
大多数人会期望以平等的方式传递传递性。这意味着当两点a
和b
相等并且a
也等于另一个点时c
,那么a
和c
应该也相等。在您的实施中不一定是这种情况。
想象每个点,在他周围有一个球体,这些点被认为是相等的。下图显示了这个球体(或更好的球体半径的一半),因此重叠意味着这些点是相等的:
所以a
andb
应该有相同的哈希码并且b
andc
应该有相同的哈希码,但不是a
and c
?这怎么可能?
我建议添加一个额外的方法is_close_to
并在那里实现逻辑。
编辑: @JLPeyret 指出,您可以使用网格并计算与包含该点的网格象限相对应的点的哈希值。在这种情况下,两个邻近点可能接近网格象限的划分,因此分配有不同的哈希值。如果这种概率方法对您有用,请查看locality-sensitive hashing。
推荐阅读
- questdb - 从 Docker 运行服务时如何查看服务的日志?
- javascript - 如果仅在 Assets 文件夹中找不到文件,Node.js Express 返回 404
- reactjs - useCallback 是 React 应用程序的性能提升吗?
- java - 如何使用 javapackager 为我的代码创建可执行文件?
- python - 在 CPU 上使用多个并行进程推断 YOLOv5 (PyTorch)
- excel - 在不同的步骤中搜索 Excel 工作表中的值
- c# - 从自定义 Json 转换器中操作 Json 字符串
- entity-framework-core - 如何在测试服务器上为代码优先方法启用脚本迁移?
- angular8 - 验证网格中的每个单元格
- c# - 将 2 个 LINQ 查询合并为 2 个