2016-08-09 310 views
4

Ich habe ein (meiner Meinung nach) merkwürdiges Verhalten beim Durchlaufen eines Julia-Wörterbuchs und beim Umbenennen von Schlüsselnamen während der Iteration erlebt. Das folgende Beispiel funktioniert wie erwartet:Julia, merkwürdiges Verhalten beim Ändern von Schlüsseln beim Durchlaufen des Wörterbuchs

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 

Returns (wie erwartet)

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

jedoch:

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 

Ergebnisse in:

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

Da die Werte und th Die Taste "bernd_one_new2_new2" zeigt an, dass mehr als drei Iterationen stattfinden (obwohl das Wörterbuch die Länge 3 hat). Das "seltsame" Verhalten kann jedoch durch Tiefkopieren der Schlüssel in ein neues Objekt behoben werden.

Ist das Verhalten wie erwartet?

Vielen Dank im Voraus!

(btw ich bin mit Julia Version 0.4.6 (2016.06.19 17.16 UTC).)

Antwort

7

Dies ist zu erwarten: Sie sind nicht sicher kann durch ein Wörterbuch durchlaufen, während es mutiert. Dies ist auch in anderen Sprachen eine häufige Einschränkung: einige davon verhindern dies; andere erlauben es, zeigen aber ein ähnliches Verhalten.

+0

Hallo Stefan, vielen Dank! – langohrschnauze

+2

Es ist ein unglückliches Problem: Es ist schwer zu überprüfen, ohne die Leistung zu beeinträchtigen, und es ist fast unmöglich, dies sicher zu machen. – StefanKarpinski

+3

Wenn die Verschwendung von etwas Zeit und Speicher in Ordnung ist, sollte das Iterieren über 'collect (Schlüssel (a))' anstelle von 'Schlüssel (a)' die erwarteten Ergebnisse bringen. –