【问题标题】:Julia dictionaries : not always unicity of dictionary keys with immutable keysJulia 字典:具有不可变键的字典键并不总是唯一的
【发布时间】:2019-03-13 22:49:33
【问题描述】:

在 Julia 0.6 中,struct 是不可变的,所以我希望函数 func1()、func2() 和 func3() 用 struct 键为字典提供只产生一条记录:

Dict(KEY("Bob", "NY", "[120 10]")=>true)

但事实并非如此,当我将字符串放入 key 结构的变量中时,键是唯一的,而当我直接使用相同的字符串时,键不是唯一的。更奇怪的是,如果我在 func3() 中使用 split 生成变量 x,y,z,则从该变量生成的键不是唯一的。

由于这些细微之处很容易出现错误,所以我在这里展示一个简单的例子:)

struct KEY
    A::String
    B::String
    C::String
end


function func1(d::Dict{KEY, Bool})  
    for i = 1:3
        x = "Bob"
        y = "NY"
        z = "[120 10]"
        d[KEY(x,y,z)] = true
    end
end

function func2(d::Dict{KEY, Bool})   
    x = "Bob"
    y = "NY"
    z = "[120 10]"
    d[KEY(x,y,z)] = true
    d[KEY(x,y,z)] = true
    d[KEY("Bob","NY","[120 10]")] = true
    d[KEY("Bob","NY","[120 10]")] = true
end

function func3(d::Dict{KEY, Bool})  
    for i = 1:3
        str = "Bob;NY;[120 10]"
        (x,y,z) = split(str, ";")
        d[KEY(x,y,z)] = true
    end
end

function  main()
    d = Dict{KEY,Bool}()
    func1(d)
    println("func1 ", d)
    d = Dict{KEY,Bool}()
    func2(d)
    println("func2 ", d)
    d = Dict{KEY,Bool}()
    func3(d)
    println("func3 ", d)
end

main()

输出是:

func1 Dict(KEY("Bob", "NY", "[120 10]")=>true)
func2 Dict(KEY("Bob", "NY", "[120 10]")=>true,KEY("Bob", "NY", "[120 10]")=>true,KEY("Bob", "NY", "[120 10]")=>true)
func3 Dict(KEY("Bob", "NY", "[120 10]")=>true,KEY("Bob", "NY", "[120 10]")=>true,KEY("Bob", "NY", "[120 10]")=>true)

【问题讨论】:

    标签: dictionary key julia


    【解决方案1】:

    tl;dr KEY 是不可变的,Strings 也是不可变的,但字符串是“复合数据类型”,因此有一个不是不可变的 data 字段。因此,您添加的不同 KEY/键实际上具有不同的哈希值。

    a = KEY("fg","g","gh")
    b = KEY("fg","g","gh")
    
    a == b # false
    # because a == b falls back to a === b
    
    a === b # false
    # because hashes are different
    Base.hash(a) == Base.hash(b) # false
    
    # because even though
    isimmutable(a) & isimmutable(a.A) & isimmutable(a.B) & isimmutable(a.C) # true
    isimmutable(a.A.data) # false
    a.A.data[1] = 0x70
    println(a) # KEY("pg","g","gh")
    

    更多解释在这里:Julia: Immutable composite typesbase/operators.jl 的来源。

    【讨论】:

      【解决方案2】:

      我将此作为答案发布,因为我认为它很重要,并且答案的寿命会比 Julia 0.6 长(尽管评论很短)。

      此行为在 Julia 0.7 上已修复。当您运行 main() 时,您将获得:

      func1 Dict(KEY("Bob", "NY", "[120 10]")=>true)
      func2 Dict(KEY("Bob", "NY", "[120 10]")=>true)
      func3 Dict(KEY("Bob", "NY", "[120 10]")=>true)
      

      正如预期的那样。

      原因是,在 Julia 0.7 中,如果 s1s2 是包含相同数据的 Strings(不一定在相同的内存位置),我们就有 s1===s2true

      这是执行比较的代码的链接:https://github.com/JuliaLang/julia/blob/master/src/builtins.c#L181

      同样已经在 J​​ulia 0.6 String 没有 data 字段。

      【讨论】:

        猜你喜欢
        • 2011-07-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-07-23
        • 2013-03-04
        • 1970-01-01
        • 2019-10-31
        • 1970-01-01
        相关资源
        最近更新 更多