【问题标题】:Julia, strange behaviour when changing keys while iterating through dictionaryJulia,在遍历字典时更改键时的奇怪行为
【发布时间】:2026-02-11 09:15:02
【问题描述】:

在遍历 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

返回(如预期)

# Dict{ASCIIString,Int64} with 3 entries:
#   "gabi_one_new"  => 11
#   "bernd_one_new" => 8
#   "klaus_one_new" => 6

但是:

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 

结果:

# Dict{ASCIIString,Int64} with 3 entries:
#   "klaus_one_new2"      => 27
#   "gabi_one_new2"       => 32
#   "bernd_one_new2_new2" => 17

正如值和键“bernd_one_new2_new2”所示,发生了超过三个迭代(尽管字典的长度为 3)。然而,“奇怪”的行为可以通过将键深度复制到新对象中来解决。

行为是否符合预期?

提前致谢!

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

【问题讨论】:

    标签: dictionary iterator julia


    【解决方案1】:

    这是意料之中的:您不能在修改字典时安全地遍历它。这也是其他语言的常见限制:其中一些会阻止您这样做;其他人允许这样做,但表现出类似的行为。

    【讨论】:

    • 这是一个不幸的问题:很难在不破坏性能的情况下进行检查,而且几乎不可能确保安全。
    • 如果浪费一点时间和内存没问题,迭代 collect(keys(a)) 而不是 keys(a) 应该会产生预期的结果。
    • 谢谢丹! collect 似乎对性能影响不大:时间比率(collect/vs iterator)= 0.72,“迭代次数”比率(collect / vs iterator)= 0.62(虽然比较有点没用,因为使用迭代器会生成错误的结果:) )