Frage Wie sortiere ich ein Wörterbuch nach Wert?


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

Ich kann die Schlüssel sortieren, aber wie kann ich basierend auf den Werten sortieren?

Hinweis: Ich habe die Stack Overflow-Frage gelesen Wie sortiere ich eine Liste von Wörterbüchern nach Werten des Wörterbuchs in Python? und wahrscheinlich könnte ich 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.


2932
2018-03-05 00:49


Ursprung


Antworten:


Es ist nicht möglich, ein Wörterbuch zu sortieren, nur um eine Darstellung eines Wörterbuchs zu erhalten, das sortiert ist. Wörterbücher sind von Natur aus fehlerfrei, andere Typen wie Listen und Tupel jedoch nicht. Sie benötigen also einen geordneten Datentyp, um sortierte Werte darzustellen. Dies ist eine Liste - wahrscheinlich eine Liste von Tupeln.

Zum Beispiel,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_x wird eine Liste von Tupeln sein, die nach dem zweiten Element in jedem Tupel sortiert sind. dict(sorted_x) == x.

Und für diejenigen, die nach Schlüsseln statt nach Werten sortieren möchten:

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

In Python3 seit dem Entpacken ist nicht erlaubt [1] wir können benutzen

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_by_value = sorted(x.items(), key=lambda kv: kv[1])

3550
2018-03-05 00:59



So einfach wie: sorted(dict1, key=dict1.get)

Nun, es ist tatsächlich möglich, eine "Sortierung nach Wörterbuchwerten" vorzunehmen. Kürzlich musste ich das in einem Code Golf (Stack Overflow Frage) machen Code Golf: Worthäufigkeitsdiagramm). Gekürzt war das Problem folgendermassen: Bei einem Text, zähle, wie oft jedes Wort angetroffen wird, und zeige eine Liste der obersten Wörter, sortiert nach abnehmender Häufigkeit.

Wenn Sie ein Dictionary mit den Wörtern als Schlüssel und der Anzahl der Vorkommen jedes Worts als Wert konstruieren, vereinfachen Sie es hier wie folgt:

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
  d[w] += 1

dann können Sie eine Liste der Wörter erhalten, sortiert nach Häufigkeit der Verwendung mit sorted(d, key=d.get) - Die Sortierung erfolgt über die Wörterbuchschlüssel, wobei die Anzahl der Wortvorkommen als Sortierschlüssel verwendet wird.

for w in sorted(d, key=d.get, reverse=True):
  print w, d[w]

Ich schreibe diese detaillierte Erklärung, um zu illustrieren, was die Leute oft meinen: "Ich kann ein Wörterbuch leicht nach Schlüssel sortieren, aber wie sortiere ich nach Wert" - und ich denke, dass das OP versuchte, ein solches Problem anzugehen. Und die Lösung besteht darin, eine Art Liste der Schlüssel zu erstellen, basierend auf den Werten, wie oben gezeigt.


967
2017-07-05 08:01



Du könntest benutzen:

sorted(d.items(), key=lambda x: x[1])

Dadurch wird das Wörterbuch nach den Werten jedes Eintrags im Wörterbuch vom kleinsten zum größten sortiert.


601
2018-02-13 16:33



Dicts können nicht sortiert werden, aber Sie können eine sortierte Liste daraus erstellen.

Eine sortierte Liste von Diktatwerten:

sorted(d.values())

Eine Liste von (Schlüssel, Wert) Paaren, sortiert nach Wert:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))

165
2018-03-05 01:05



In den letzten Python 2.7 haben wir das neue OrderedDict Typ, der sich an die Reihenfolge erinnert, in der die Artikel hinzugefügt wurden.

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

Um ein neues geordnetes Wörterbuch aus dem Original zu erstellen, sortieren Sie nach den Werten:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

Das OrderedDict verhält sich wie ein normales Diktat:

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

128
2017-07-05 02:50



UPDATE: 5. Dezember 2015 mit Python 3.5

Während ich die akzeptierte Antwort nützlich fand, war ich auch überrascht, dass sie nicht zum Nachschlagen aktualisiert wurde OrderedDict aus der Standardbibliothek Sammlungen Modul als eine lebensfähige, moderne Alternative - entworfen, um genau diese Art von Problem zu lösen.

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)])

Das offizielle OrderedDict Die Dokumentation bietet ein sehr ähnliches Beispiel, aber ein Lambda 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)])

75
2017-12-05 09:46



Es kann oft sehr praktisch sein zu verwenden Namedtuple. Zum Beispiel haben Sie ein Wörterbuch mit 'Name' als Schlüssel und 'score' als Werte und Sie wollen nach 'score' 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())

Sortieren 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 von, sagen wir der zweitbeste Spieler (Index = 1) sehr pythonisch wie folgt erhalten:

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

64
2017-08-30 00:30



Ziemlich genau so wie Hank Gay's Antwort;


    sortiert ([(value, key) für (key, value) in mydict.items ()])

Oder optimiert ein bisschen wie von John Fouhy vorgeschlagen;


    sortiert ((Wert, Schlüssel) für (Schlüssel, Wert) in mydict.items ())


57
2018-03-05 01:06



Ab Python 3.6 Das eingebaute Diktat wird bestellt

Gute Neuigkeiten, so sollte der ursprüngliche Anwendungsfall des OPs, Mappings aus einer Datenbank mit eindeutigen String-IDs als Schlüssel und numerische Werte wie Werte in ein integriertes Python v3.6 + -Dict zu übernehmen, nun die Einfügereihenfolge berücksichtigen.

Wenn die resultierenden zwei Spaltentabellenausdrücke von einer Datenbankabfrage wie sagen:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

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

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

Erlaube es später auszugeben als:

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

in diesem Fall (für das neue eingebaute Python 3.6 + -Dict!)

foo 0
bar 1
baz 42

in der gleichen Reihenfolge pro Wert von v.

Wo in Python 3.5 auf meinem Rechner installiert wird, gibt es momentan:

bar 1
foo 0
baz 42

Einzelheiten:

Wie im Jahr 2012 von Raymond Hettinger vorgeschlagen (siehe Mail auf Python-Dev mit Thema "Kompaktere Wörterbücher mit schnellerer Iteration") und jetzt (im Jahr 2016) in einer Mail von Victor Stinner auf Python-Dev mit Thema angekündigt "Python 3.6 dict wird kompakt und erhält eine private Version; Keywords werden geordnet" aufgrund der Reparatur / Implementierung von Problem 27350 "Kompakt und geordnete Diktatur" In Python 3.6 werden wir nun in der Lage sein, ein eingebautes dict zu verwenden, um die Reihenfolge der Einfügung beizubehalten !!

Hoffentlich wird dies zu einer Implementierung von LayerDeter als erste Stufe führen. Wie @ JimFasarakis-Hilliard angegeben hat, sehen einige auch in Zukunft Anwendungsfälle für den OrderedDict-Typ. Ich denke, dass die Python-Gemeinschaft im Allgemeinen sorgfältig prüfen wird, ob dies den Test der Zeit bestehen wird und was die nächsten Schritte sein werden.

Zeit, unsere Programmiergewohnheiten zu überdenken, um nicht die Möglichkeiten zu verpassen, die sich durch stabile Anordnung von:

  • Schlüsselwortargumente und
  • (Zwischen-) Diktatspeicher

Das erste, weil es den Versand in der Implementierung von Funktionen und Methoden in einigen Fällen erleichtert.

Die zweite, wie es ermutigt, leichter zu verwenden dicts als Zwischenlager in verarbeitenden Pipelines.

Raymond Hettinger hat freundlicherweise Unterlagen zur Verfügung gestellt, die erklären "Die Tech Behind Python 3.6 Wörterbücher"- von seiner San Francisco Python Meetup Group Präsentation 2016-DEC-08.

Und vielleicht erhalten einige hochgestaltete Frage- und Antwort-Seiten von Stack Overflow Varianten dieser Informationen und viele qualitativ hochwertige Antworten erfordern auch eine Aktualisierung per Version.

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

Wie @ajcr zu Recht bemerkt: "Der auftragserhaltende Aspekt dieser neuen Implementierung wird als ein Implementierungsdetail betrachtet und sollte nicht verlässlich sein." (von dem whatsnew36) nicht nit picking, aber das Zitat wurde ein wenig pessimistisch geschnitten ;-). Es geht weiter wie "(Dies kann sich in der Zukunft ändern, aber es ist wünschenswert, diese neue dict-Implementierung in der Sprache für einige Releases zu haben, bevor die Sprachspezifikation geändert wird, um eine Ordnung erhaltende Semantik für alle aktuellen und zukünftigen Python-Implementierungen vorzuschreiben hilft, die Rückwärtskompatibilität mit älteren Versionen der Sprache beizubehalten, in denen die zufällige Iterationsreihenfolge noch immer wirksam ist, z. B. Python 3.5). "

Wie in einigen menschlichen Sprachen (z. B. Deutsch), prägt die Verwendung die Sprache, und der Wille wurde nun ... in whatsnew36.

Update 2017-12-15:

In einem Mail an die Python-Dev-ListeGuido van Rossum erklärte:

Mach es so. "Dict behält die Reihenfolge der Anzeigen" ist das Urteil. Vielen Dank!

Der CPython-Nebeneffekt der dict-Einfügereihenfolge der Version 3.6 wird nun Teil der Sprachspezifikation (und nicht mehr nur ein Implementierungsdetail). Dieser Mail-Thread brachte auch einige unterscheidende Design-Ziele ans Tageslicht collections.OrderedDict erinnert Raymond Hettinger im Gespräch.


48
2017-09-10 10:05



Gegebenes Wörterbuch

e = {1:39, 4:34, 7:110, 2:87}

Sortierung

sred = sorted(e.items(), key=lambda value: value[1])

Ergebnis

[(4, 34), (1, 39), (2, 87), (7, 110)]

Sie können eine Lambda-Funktion verwenden, um Dinge nach Wert zu sortieren und sie in einer Variable zu speichern, in diesem Fall sred mit e das ursprüngliche Wörterbuch.

Ich hoffe, das hilft!


41
2018-01-25 14:54



Ich hatte das gleiche Problem und habe es so gelöst:

WantedOutput = sorted(MyDict, key=lambda x : MyDict[x]) 

(Leute, die antworten "Es ist nicht möglich, ein Diktat zu sortieren", haben die Frage nicht gelesen! Tatsächlich "kann ich nach den Schlüsseln sortieren, aber wie kann ich basierend auf den Werten sortieren?" Bedeutet eindeutig, dass er eine Liste von die Schlüssel sortiert nach dem Wert ihrer Werte.)

Bitte beachten Sie, dass die Reihenfolge nicht gut definiert ist (Schlüssel mit dem gleichen Wert werden in der Ausgabeliste in einer beliebigen Reihenfolge sein).


36
2017-11-18 14:19