我遇到了一个试图使用字典的问题,该字典的键是包含复合类型的元组。
以下是复制我的问题的最小示例:
import Base: hash, isequal
type T
a :: Int
b :: Int
end
function isequal(A::(T,Int), B::(T,Int))
A[1].a == B[1].a && A[1].b == B[1].b && A[2] == B[2]
end
function hash(A::(T,Int))
hash(A[1].a + A[1].b + A[2])
end
d = Dict{(T,Int),Int}()
d[(T(1,1),1)] = 1
d[(T(2,2),2)] = 2
r = (T(2,2),2)
for k in keys(d)
println(isequal(r, k) && hash(r) == hash(k))
end
println(d[r])
运行此结果:
false
true
ERROR: key not found: (T(2,2),2)
所以isequal
和hash
有效,但由于某些原因,dict不是。
有谁知道发生了什么事?谢谢。
答案 0 :(得分:1)
在这种情况下,我不太了解有关元组和调度的类型,但基本上you need to implement the two argument form of hash
for this case。以下非常相似的代码按预期工作,作为比较点,没有两个参数形式:
type T
a::Int
b::Int
end
function Base.isequal(A::T, B::T)
println("isequal", A, " ", B)
A.a == B.a && A.b == B.b
end
function Base.hash(A::T)
println("hash", A)
hash(A.a + A.b)
end
d = Dict{T,Int}()
d[T(1,1)] = 1
d[T(2,2)] = 2
println("test")
r = T(2,2)
println(d[r])
带输出
isequalT(1,1) T(1,1)
hashT(1,1)
isequalT(2,2) T(2,2)
hashT(2,2)
test
hashT(2,2)
isequalT(2,2) T(2,2)
2
答案 1 :(得分:0)
问题可以通过创建hash
&来解决。 isequal
函数用于每个复合类型而不是整个元组。
如果你的密钥是(T,Int)
:
而不是:
function isequal(A::(T,Int), B::(T,Int))
A[1].a == B[1].a && A[1].b == B[1].b && A[2] == B[2]
end
function hash(A::(T,Int))
hash(A[1].a + A[1].b + A[2])
end
这样做:
function isequal(A::T, B::T)
A.a == B.a && A.b == B.b
end
function hash(A::T)
hash(A.a + A.b)
end
如果您希望原始配方有效,则必须使用可选的第二个参数指定Base.hash:h::Uint64
:
function isequal(A::(T,Int), B::(T,Int))
A[1].a == B[1].a && A[1].b == B[1].b && A[2] == B[2]
end
function hash(A::(T,Int))
hash(A[1].a + A[1].b + A[2])
end
function hash(A::(T,Int), h::Uint64)
hash(A[1].a + A[1].b + A[2] + h)
end