2008-09-13 18 views

Antwort

49

Der Standard Python dict ist nicht dazu in der Lage.

Es gibt einen Vorschlag (PEP 372), ein "geordnetes Wörterbuch" (das die Reihenfolge der Einfügung verfolgt) zum collections-Modul in der Standardbibliothek hinzuzufügen. Es enthält Links zu variousimplementationsofordereddictionaries (siehe auch diese tworecipes im Python Cookbook).

Sie könnten bei der Referenzimplementierung in der PEP bleiben, wenn Sie möchten, dass Ihr Code mit der "offiziellen" Version kompatibel ist (wenn der Vorschlag schließlich akzeptiert wird).

EDIT: Die PEP wurde akzeptiert und in Python 2.7 und 3.1 hinzugefügt. Siehe .

6

Sie können dies nicht mit der Basis-dict-Klasse tun - sie ist nach Hash sortiert. Sie könnten Ihr eigenes Wörterbuch erstellen, das wirklich eine Liste von Schlüssel-, Wertpaaren oder dergleichen ist, die geordnet werden würden.

+2

Ihre Wörterbuch-Implementierung kann stattdessen ein Standardwörterbuch und eine Liste verwenden - das Wörterbuch speichert den Schlüssel-> Wert Assoziationen, und die Liste speichert Schlüssel in der Reihenfolge der y sind eingefügt. –

18

Die anderen Antworten sind korrekt; Es ist nicht möglich, aber Sie könnten das selbst schreiben. Für den Fall, dass Sie sich nicht sicher sind, wie Sie etwas so implementieren können, finden Sie hier eine vollständige und funktionierende Implementierung der Unterklasse dict, die ich gerade geschrieben und getestet habe. (Beachten Sie, dass die Reihenfolge der Werte an den Konstruktor übergeben ist nicht definiert, aber wird kommen, bevor Werte später vergangen, und man kann immer nur nicht erlauben bestellt dicts mit Werten initialisiert werden.)

class ordered_dict(dict): 
    def __init__(self, *args, **kwargs): 
     dict.__init__(self, *args, **kwargs) 
     self._order = self.keys() 

    def __setitem__(self, key, value): 
     dict.__setitem__(self, key, value) 
     if key in self._order: 
      self._order.remove(key) 
     self._order.append(key) 

    def __delitem__(self, key): 
     dict.__delitem__(self, key) 
     self._order.remove(key) 

    def order(self): 
     return self._order[:] 

    def ordered_items(self): 
     return [(key,self[key]) for key in self._order] 


od = ordered_dict() 
od["hello"] = "world" 
od["goodbye"] = "cruel world" 
print od.order()   # prints ['hello', 'goodbye'] 

del od["hello"] 
od["monty"] = "python" 
print od.order()   # prints ['goodbye', 'monty'] 

od["hello"] = "kitty" 
print od.order()   # prints ['goodbye', 'monty', 'hello'] 

print od.ordered_items() 
# prints [('goodbye','cruel world'), ('monty','python'), ('hello','kitty')] 
+0

Ist order_dict (('key_a', 'value_a'), ('key_b', 'value_b')) korrekt sortiert? Sieht so aus, als würde _order auf self.keys() in __init__ gesetzt werden, was in der Hash-Reihenfolge angeordnet ist, nicht in der Reihenfolge, in der es eingegeben wurde? Nur neugierig. –

+0

Sie sind richtig, weshalb ich sagte, "die Reihenfolge der an den Konstruktor übergebenen Werte ist nicht definiert, wird aber kommen, bevor die Werte später übergeben werden". Es wäre möglich, diese richtig zu ordnen, aber ich war mir nicht sicher, ob das ein gewünschtes Verhalten war, da wohl solche Objekte gleichzeitig eingefügt werden. –

0

wenn Sie nicht brauchen, die dict-Funktionalität, und müssen nur Tupel in der Reihenfolge zurückgeben, in der Sie sie eingefügt haben, würde eine Queue nicht besser funktionieren?

7

Oder stellen Sie einfach den Schlüssel ein Tupel mit time.now() als das erste Feld in dem Tupel.

Dann können Sie die Schlüssel mit dictname.keys(), sortieren und voila!

Gerry

+1

Dies macht es unmöglich, Einträge im Diktat nachzuschlagen, ohne genau zu wissen, wann Sie sie eingefügt haben. Es ist nicht besser als eine Liste von Schlüssel-Wert-Paaren. – user2357112

1

Es ist nicht möglich, es sei denn, Sie die Schlüssel in einer separaten Liste gespeichert werden später für die Referenzierung.

2

oder eine der Implementierungen für die PEP-372 verwenden beschrieben here, wie die odict module vom pythonutils.

Ich habe erfolgreich die Pocoo verwendet.org Implementierung ist es so einfach wie Ihr

my_dict={} 
my_dict["foo"]="bar" 

mit

my_dict=odict.odict() 
my_dict["foo"]="bar" 

ersetzen und benötigen nur this file

1

Was können Sie tun, ist es, die Werte mit einem Schlüssel einfügen repräsentiert die Reihenfolge eingegeben werden, und Rufen Sie dann sorted() über die Artikel an.

>>> obj = {} 
>>> obj[1] = 'Bob' 
>>> obj[2] = 'Sally' 
>>> obj[3] = 'Joe' 
>>> for k, v in sorted(obj.items()): 
...  print v 
... 
Bob 
Sally 
Joe 
>>> 
+1

Wenn wir den Schlüssel für andere Zwecke nicht bereits brauchten, würden wir eine Liste verwenden. Das tut nichts, was eine Liste nicht besser macht. – user2357112

+1

@ user2357112, jedoch drückt dies eine andere Methode aus ** was der OP verlangt **. Der OP fragte nicht, wie die Artikel in der Reihenfolge gedruckt werden sollten, in der sie eingefügt wurden. Das OP sagte, wie man die Artikel ** in einem "Diktat" ** druckt. Großer Unterschied. –

+0

Sie haben das Format des Diktats so geändert, dass es für den ursprünglichen Zweck unbrauchbar wird. Wenn das Diktat ursprünglich beispielsweise Namen mit Telefonnummern verknüpft hat, haben Sie eine konsistente Iterationsreihenfolge erhalten, aber Sie haben keine Ahnung, was Bobs Telefonnummer ist. – user2357112

6

Verwenden OrderedDict() verfügbar seit Version 2.7

Nur eine Frage der Neugier:

from collections import OrderedDict 
a = {} 
b = OrderedDict() 
c = OredredDict() 

a['key1'] = 'value1' 
a['key2'] = 'value2' 

b['key1'] = 'value1' 
b['key2'] = 'value2' 

c['key2'] = 'value2' 
c['key1'] = 'value1' 

print a == b #True 
print a == C#True 
print b == C#False 
Verwandte Themen