3413 Stimmen

Wie kann ich ein Wörterbuch nach Wert sortieren?

Ich habe ein Wörterbuch mit Werten, die aus zwei Feldern in einer Datenbank gelesen werden: ein Zeichenfolgenfeld und ein numerisches Feld. Das String-Feld ist eindeutig, daher ist es der Schlüssel des Wörterbuchs.

Ich kann nach den Schlüsseln sortieren, aber wie kann ich nach den Werten sortieren?

Hinweis: Ich habe die Stack Overflow-Frage hier gelesen Wie kann ich eine Liste von Wörterbüchern nach einem Wert des Wörterbuchs sortieren? und könnte wahrscheinlich meinen Code ändern, um eine Liste von Wörterbüchern zu haben, aber da ich nicht wirklich eine Liste von Wörterbüchern brauche, wollte ich wissen, ob es eine einfachere Lösung gibt, um entweder in aufsteigender oder absteigender Reihenfolge zu sortieren.

125voto

arcseldon Punkte 32403

UPDATE: 5 DEZEMBER 2015 mit Python 3.5

Ich fand die akzeptierte Antwort zwar nützlich, war aber auch überrascht, dass sie nicht aktualisiert wurde, um auf die OrderedDict aus der Standardbibliothek Sammlungen Modul als eine praktikable, moderne Alternative, die genau diese Art von Problemen lösen soll.

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

Die offizielle OrderedDict Dokumentation bietet ebenfalls ein sehr ähnliches Beispiel, allerdings unter Verwendung eines Lambdas für die Sortierfunktion:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

115voto

user26294 Punkte 5105

Ziemlich genau dasselbe wie Hank Gay's Antwort :

sorted([(value,key) for (key,value) in mydict.items()])

Oder leicht optimiert, wie von John Fouhy vorgeschlagen:

sorted((value,key) for (key,value) in mydict.items())

87voto

Dilettant Punkte 3130

Ab dem Python 3.6 das eingebaute Diktat wird bestellt

Gute Nachrichten, so dass die OP's ursprünglichen Anwendungsfall der Zuordnung Paare aus einer Datenbank mit eindeutigen String-IDs als Schlüssel und numerische Werte als Werte in einem eingebauten Python v3.6+ Diktat abgerufen, sollte nun die Einfügereihenfolge zu respektieren.

Wenn zum Beispiel die resultierenden zweispaltigen Tabellenausdrücke aus einer Datenbankabfrage wie:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

in zwei Python-Tupeln, k_seq und v_seq (natürlich nach numerischem Index ausgerichtet und mit gleicher Länge), gespeichert werden würde:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

Später ausgeben lassen als:

for k, v in ordered_map.items():
    print(k, v)

in diesem Fall (für das neue in Python 3.6+ eingebaute Diktat!):

foo 0
bar 1
baz 42

in der gleichen Reihenfolge pro Wert von v.

Wo in der Python 3.5-Installation auf meinem Rechner ergibt es derzeit:

bar 1
foo 0
baz 42

Einzelheiten:

Wie 2012 von Raymond Hettinger vorgeschlagen (vgl. Mail auf python-dev mit Betreff "Kompaktere Wörterbücher mit schnellerer Iteration" ) und nun (im Jahr 2016) in einer Mail von Victor Stinner an python-dev mit dem Betreff "Python 3.6 dict wird kompakt und bekommt eine private Version; und Schlüsselwörter werden geordnet" aufgrund der Behebung/Umsetzung von Problem 27350 "Kompaktes und geordnetes Diktat" in Python 3.6 werden wir nun in der Lage sein, ein eingebautes Diktat zu verwenden, um die Einfügereihenfolge beizubehalten!!

Hoffentlich wird dies in einem ersten Schritt zu einer dünnschichtigen OrderedDict-Implementierung führen. Wie @JimFasarakis-Hilliard andeutete, sehen einige auch in Zukunft Anwendungsfälle für den OrderedDict-Typ. Ich denke, die Python-Gemeinschaft insgesamt wird sorgfältig prüfen, ob dies den Test der Zeit bestehen wird und was die nächsten Schritte sein werden.

Es ist an der Zeit, unsere Kodierungsgewohnheiten zu überdenken, um die Möglichkeiten nicht zu verpassen, die sich durch die stabile Anordnung von eröffnen:

  • Schlüsselwortargumente und
  • (Zwischen-)Lagerung von Diktaten

Erstens, weil es die Abfertigung bei der Implementierung von Funktionen und Methoden in einigen Fällen erleichtert.

Die zweite, weil sie dazu anregt, leichter die dict s als Zwischenspeicher in Verarbeitungspipelines.

Raymond Hettinger hat freundlicherweise eine Dokumentation zur Verfügung gestellt, die erklärt " Die Technik hinter den Python 3.6-Wörterbüchern " - aus seiner Präsentation der San Francisco Python Meetup Group 2016-DEC-08.

Und vielleicht werden einige hochdekorierte Frage- und Antwortseiten von Stack Overflow Varianten dieser Informationen erhalten und viele hochqualitative Antworten werden ebenfalls ein Update pro Version erfordern.

Caveat Emptor (siehe aber auch unten Update 2017-12-15):

Wie @ajcr zu Recht anmerkt: "Der ordnungserhaltende Aspekt dieser neuen Implementierung ist ein Implementierungsdetail und sollte nicht als verlässlich angesehen werden." (aus der whatsnew36 ) keine Erbsenzählerei, sondern das Zitat wurde ein wenig pessimistisch geschnitten ;-). Weiter heißt es: "(Dies kann sich in der Zukunft ändern, aber es ist erwünscht, diese neue dict-Implementierung in der Sprache für ein paar Versionen zu haben, bevor die Sprachspezifikation geändert wird, um eine ordnungserhaltende Semantik für alle aktuellen und zukünftigen Python-Implementierungen vorzuschreiben; dies hilft auch, die Rückwärtskompatibilität mit älteren Versionen der Sprache zu bewahren, in denen die zufällige Iterationsreihenfolge noch in Kraft ist, z.B. Python 3.5)."

Wie in einigen menschlichen Sprachen (z.B. Deutsch) prägt also der Sprachgebrauch die Sprache, und der Wille ist nun erklärt worden ... in whatsnew36 .

Update 2017-12-15:

In einem Mail an die python-dev-Liste erklärte Guido van Rossum:

Machen Sie es so. "Dict behält die Einfügereihenfolge bei" ist die Regel. Danke!

Der CPython-Seiteneffekt der Diktateinfüge-Reihenfolge in Version 3.6 wird nun also Teil der Sprachspezifikation (und nicht mehr nur ein Implementierungsdetail). Dieser Mail-Thread hat auch einige besondere Design-Ziele für collections.OrderedDict wie von Raymond Hettinger in der Diskussion angemahnt.

84voto

Remi Punkte 19243

Es kann oft sehr praktisch sein, wenn man namedtuple . Ein Beispiel: Sie haben ein Wörterbuch mit den Schlüsseln "Name" und "Punktzahl" als Werte und möchten nach "Punktzahl" sortieren:

import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}

Sortierung mit der niedrigsten Punktzahl zuerst:

worst = sorted(Player(v,k) for (k,v) in d.items())

Sortierung mit der höchsten Punktzahl zuerst:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

Jetzt können Sie den Namen und die Punktzahl des zweitbesten Spielers (Index = 1) auf sehr pythonische Weise ermitteln, z. B. so:

player = best[1]
player.name
    'Richard'
player.score
    7

60voto

Maxime Chéramy Punkte 16289

Beginnend mit Python 3.6, dict Objekte sind jetzt nach der Einfügereihenfolge geordnet. Das steht offiziell in den Spezifikationen von Python 3.7.

>>> words = {"python": 2, "blah": 4, "alice": 3}
>>> dict(sorted(words.items(), key=lambda x: x[1]))
{'python': 2, 'alice': 3, 'blah': 4}

Davor mussten Sie OrderedDict .

Python 3.7 Dokumentation sagt:

Geändert in Version 3.7: Die Reihenfolge im Wörterbuch ist garantiert die Einfüge Reihenfolge. Dieses Verhalten war ein Implementierungsdetail von CPython aus Version 3.6.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X