Julia:包含复合类型的元组键的字典

时间:2014-10-20 03:23:52

标签: julia

我遇到了一个试图使用字典的问题,该字典的键是包含复合类型的元组。

以下是复制我的问题的最小示例:

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)

所以isequalhash有效,但由于某些原因,dict不是。

有谁知道发生了什么事?谢谢。

2 个答案:

答案 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