Julia,在迭代字典时更改键时的奇怪行为

lan*_*uze 3 dictionary iterator julia

我经历了(在我看来)奇怪的行为,同时迭代Julia字典并在迭代期间查找键名.以下示例按预期工作:

a = Dict("klaus_one" => 3,
         "bernd_one" => 5,
         "gabi_one" => 8)

for i= keys(a)
     x = pop!(a,i)
     a[join([i,"new"],"_")] = x + 3
end
Run Code Online (Sandbox Code Playgroud)

退货(按预期)

# Dict{ASCIIString,Int64} with 3 entries:
#   "gabi_one_new"  => 11
#   "bernd_one_new" => 8
#   "klaus_one_new" => 6
Run Code Online (Sandbox Code Playgroud)

然而:

a = Dict("klaus_one" => 3,
         "bernd_one" => 5,
         "gabi_one" => 8)

for i=1:5

    if i!=1

        # _keys = deepcopy(keys(a))
        _keys = keys(a)
        for k = _keys
            k_base = join(split(k,"_")[1:2],"_")
            a[k_base] = pop!(a,k) + 3 
        end
    end
    # _keys = deepcopy(keys(a))
     _keys = keys(a)

    for k = _keys
        k_new = join([k,"new2"],"_")
        a[k_new] = pop!(a,k) 
    end
end 
Run Code Online (Sandbox Code Playgroud)

结果是:

# Dict{ASCIIString,Int64} with 3 entries:
#   "klaus_one_new2"      => 27
#   "gabi_one_new2"       => 32
#   "bernd_one_new2_new2" => 17
Run Code Online (Sandbox Code Playgroud)

当值和键"bernd_one_new2_new2"显示时,发生三次以上的迭代(尽管字典长度为3).然而,通过将键深入复制到新对象中可以解决"奇怪"行为.

行为是否符合预期?

提前致谢 !

(顺便说一句.我使用的是Julia Version 0.4.6(2016-06-19 17:16 UTC))

Ste*_*ski 6

这是预期的:你不能安全地迭代字典,同时改变它.这也是其他语言的常见限制:其中一些禁止你这样做; 其他人允许它但表现出类似的行为.

  • 如果浪费了一点时间和内存就可以了,迭代`collect(keys(a))`而不是`keys(a)`应该产生预期的结果. (3认同)
  • 这是一个不幸的问题:如果没有破坏性能,很难检查,而且几乎不可能使这个安全. (2认同)