How to use haskey() and in() functions with complex dictionnary keys in Julia?

Viewed 810

haskey() and in() functions are very useful to test the content of dictionaries in Julia :

julia> dict = Dict("a" => 1, "b" => 2, "c" => 3, "d" => 4, "e" => 5)
Dict{String,Int64} with 5 entries:
  "c" => 3
  "e" => 5
  "b" => 2
  "a" => 1
  "d" => 4

julia> haskey(dict, "a")
true

julia> in(("a" => 1), dict)
true

but I was surprised by their behavior with complex keys :

julia> immutable MyT
           A::String
           B::Int64
       end

julia> a = Dict(MyT("Tom",191)=>1,MyT("Bob",20)=>1,MyT("Jo",315)=>1,MyT("Luc",493)=>1)
Dict{MyT,Int64} with 4 entries:
  MyT("Tom",191) => 1
  MyT("Jo",315)  => 1
  MyT("Bob",20)  => 1
  MyT("Luc",493) => 1

julia> keys(a)
Base.KeyIterator for a Dict{MyT,Int64} with 4 entries. Keys:
  MyT("Tom",191)
  MyT("Jo",315)
  MyT("Bob",20)
  MyT("Luc",493)

julia> haskey(a, MyT("Tom",191))
false

julia> in((MyT("Tom",191) => 1), a)
false

What I did wrong ? Thank you very much for your comments !

Thanks to @Michael K. Borregaard, I can propose this solution :

a = Dict{MyT, Int64}()

keyArray = Array{MyT,1}()
keyArray = [MyT("Tom",191),MyT("Bob",20),MyT("Jo",315),MyT("Luc",493)]

for i in keyArray
    a[i] = 1
end

println(a)
# Dict(MyT("Tom",191)=>1,MyT("Tom",191)=>1,MyT("Luc",493)=>1,MyT("Jo",315)=>1,MyT("Luc",493)=>1,MyT("Bob",20)=>1,MyT("Jo",315)=>1,MyT("Bob",20)=>1)

keyArray[1]            # MyT("Tom",191)
haskey(a, keyArray[1]) # true

But I have to store keys in a separate array. This means that can't warranty the unicity of the keys which is the strength of the dictionaries and why I choose to use it :(

So I have to use another step :

unique(keyArray)

Another better solution :

function CompareKeys(k1::MyT, k2::MyT)
    if k1.A == k2.A &&  k1.B == k2.B
        return true
    else 
        return false
    end
end

function ExistKey(k::MyT, d::Dict{MyT, Int64})
    for i in keys(d)
        if CompareKeys(k, i)
            return true
        end
    end
    return false
end

a = Dict(MyT("Tom",191)=>1,MyT("Bob",20)=>1,MyT("Jo",315)=>1,MyT("Luc",493)=>1)

ExistKey(MyT("Tom",192),a) # false

ExistKey(MyT("Tom",191),a) # true

Compared to Julia, Go is more straightforward for this problem :

package main

import (
    "fmt"
)

type MyT struct {
    A string
    B int
}

func main() {

    dic := map[MyT]int{MyT{"Bob", 10}: 1, MyT{"Jo", 21}: 1}

    if _, ok := dic[MyT{"Bob", 10}]; ok {
        fmt.Println("key exists")
    }
}
// answer is "key exists"
4 Answers
Related