2016-08-17 2 views
4

Bei einer Dict werden values(...) und keys(...) Artikel in der richtigen Reihenfolge zurückgegeben?Werte und Schlüssel garantiert in der beständigen Reihenfolge?

Mit anderen Worten, ist zip(keys(d), values(d)) garantiert genau die Schlüssel-Wert-Paare des Wörterbuchs enthalten d?

+2

Ich werde feststellen, dass in der Definition des Wörterbuchtyps im Quellcode (https://github.com/JuliaLang/julia/blob/master/base/dict.jl) die Schlüssel und Werte als Array gespeichert werden Objekte, die geordnet sind. Daher bin ich mir ziemlich sicher, dass sie ihre Bestellung aufrechterhalten werden, aber ich konnte nicht darauf schwören. –

+2

Beachten Sie auch den 'OrderedDict' Typ im' DataStructures' Modul. Dieser garantiert garantiert die bestellte Bestellung. Es gibt ein bisschen mehr Aufwand, aber nicht viel. Und da Sie sich nicht auf ein "unter der Haube", undokumentiertes Problem im Quellcode verlassen, das durch die gleichen Versionen beibehalten wird, ist es wahrscheinlich ein bisschen sicherer. –

+0

@MichaelOhlrogge Ja, mit Blick auf 'dict.jl' sehe ich, dass' Werte (Dict) 'und' Schlüssel (Dict) 'einfach das' Dict' iterieren und den Schlüssel bzw. den Wert jedes Elements extrahieren. Daher sind sie in der gleichen Reihenfolge. Es wäre jedoch schöner, wenn dies in der Dokumentation garantiert wäre. Hoffentlich wird sich das in Zukunft nicht ändern. – becko

Antwort

6

Option 1

Die Stromquelle Julia code zeigt an, dass die Schlüssel und vals eines Objekts als Dict()Array Objekte gespeichert sind, die geordnet. So können Sie einfach values() und keys() separat verwenden, wie in Ihrer Frage Formulierung. Es ist jedoch gefährlich, sich auf Details zu verlassen, die nicht dokumentiert sind, da sie ohne vorherige Ankündigung geändert werden können.

Option 2

Ein OrderedDict vom DataStructures Paket (zusammen mit den Funktionen values() und keys()) ist wahrscheinlich die einfachste und sicherste Weg, um sicher konsistenter Ordnung zu sein. Es ist in Ordnung, wenn Sie die Bestellung nicht speziell benötigen.

Option 3

Wenn Sie nicht mit dem zusätzlichen Aufwand für die Installation und das Laden des DataStructures Paket beschäftigen möchten, können Sie nur die für den Umgang mit dieser Art der Sache in Syntax Julia gebaut, zum Beispiel

Mydict = Dict("a" => 1, "b" => 2, "c" => 1) 

a = [(key, val) for (key, val) in Mydict] 

Die Verwendung von zip() wie in der Frage Formulierung gegeben kommt noch hinzu, Komplexität und Risiken in dieser Situation.

Wenn Sie die Entitäten trennen möchten, können Sie dann verwenden:

Keys = [key for (key, val) in Mydict] 
Values = [val for (key, val) in Mydict] 

oder beziehen sich nur auf a[idx][1] für das idx Element Keys, wenn Sie es brauchen.

3

Derzeit scheint Ihre Behauptung wahr zu sein:

julia> let 
      d = [i => i^2 for i in 1:10_000] 
      z = zip(keys(d), values(d)) 
      for (pair, tupl) in zip(d, z) 
       @assert pair[1] == tupl[1] && pair[2] == tupl[2] 
      end 
      info("Success") 
     end 
INFO: Success 

Aber das ist eine nicht dokumentierte Implementierung detailliert wie Michael Ohlrogge erklärt.

Stefan Karpinski Kommentar über Show (dict) jetzt von Schlüssel in #16743 sortiert:

Dies hat Auswirkungen auf die Leistung für den Druck sehr groß Dicts. Ich denke nicht, dass es eine gute Idee ist. Ich denke jedoch, dass es eine gute Idee ist, Dict zu bestellen.

Siehe auch:

  • #10116WIP: bestellt versuchen Dict Darstellung.

Am wichtigsten, was versuchst du zu tun? Vielleicht ist ein OrederedDict was Sie brauchen?

+0

Es ist mir egal, das 'Dict' wird bestellt. Was ich will, ist, dass die von 'keys' zurückgegebene Reihenfolge (was auch immer es ist) mit der Reihenfolge übereinstimmt, die durch' values' gegeben ist. – becko

1

Ein anderer Weg, um zwischen entsprechenden Schlüsseln und Werten, um sicherzustellen, imap vom Iteratoren Paket in der folgenden Weise verwendet:

kann für andere Strukturen potenziell angepasst
using Iterators 
d = Dict(1=>'a',2=>'b',3=>'c') 

# keys iterator is `imap(first,d)` 
julia> collect(imap(first,d)) 
3-element Array{Any,1}: 
2 
3 
1 

# values iterator is `imap(last,d)` 
julia> collect(imap(last,d)) 
3-element Array{Any,1}: 
'b' 
'c' 
'a' 

diese Methode. Alle anderen Kommentare und Antworten sind auch gut.

+1

Natürlich kann das Wörterbuch nicht zwischen dem Iterieren von Werten und Schlüsseln geändert werden. Darüber hinaus muss der Wörterbuch-Iterator deterministisch sein (man kann sich eine zufällige oder nicht-konstante Reihenfolge der Iteration in einem Wörterbuch vorstellen) - das ist zur Zeit der Fall. Schließlich ist die vorgeschlagene Methode in Laufzeit und Speicher relativ effizient. –

2

Ja, keys und values Artikel in der richtigen Reihenfolge zurücksenden. Es sei denn, wie Dan Getz oben ausgeführt hat, wird das Wörterbuch zwischen den beiden Iteratoren modifiziert.

Ich denke, es wäre relativ pervers für ein Wörterbuch, dieses Verhalten nicht zu haben. Es war für uns offensichtlich, dass die Reihenfolge übereinstimmen sollte, bis zu dem Punkt, dass es uns nicht einmal einfiel, dies explizit in der Dokumentation zu erwähnen.

+1

Es würde nicht schaden, dies explizit in der Dokumentation anzugeben. – becko

Verwandte Themen