Wie sortiere ich ein Wörterbuch nach Wert?


3422

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

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

Hinweis: Ich habe hier die Frage zum Stapelüberlauf gelesen. Wie sortiere ich eine Liste von Wörterbüchern nach einem Wert des Wörterbuchs? 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 benötige, wollte ich wissen, ob es eine einfachere Lösung gibt, um entweder in aufsteigender oder absteigender Reihenfolge zu sortieren.


9
Die Wörterbuchdatenstruktur hat keine inhärente Reihenfolge. Sie können es durchlaufen, aber es gibt nichts, was garantieren könnte, dass die Iteration einer bestimmten Reihenfolge folgt. Dies ist beabsichtigt, daher ist es am besten, wenn Sie eine andere Datenstruktur zur Darstellung verwenden.
Daishiman

135
"sortiert ()" kann mit Wörterbüchern arbeiten (und gibt eine Liste sortierter Schlüssel zurück), daher denke ich, dass er sich dessen bewusst ist. Ohne sein Programm zu kennen, ist es absurd, jemandem zu sagen, dass er die falsche Datenstruktur verwendet. Wenn Sie in 90% der Fälle schnelle Suchvorgänge benötigen, ist ein Diktat wahrscheinlich das, was Sie wollen.
Bobpaul

Alle drei Ausgaben (Schlüssel, Werte, beide) zum Sortieren von Wörterbüchern werden hier in einem klaren und präzisen Stil behandelt: stackoverflow.com/questions/16772071/sort-dict-by-value-python
JStrahl

2
@Daishiman Die Basisklasse ist möglicherweise nicht bestellt, aber OrderedDict ist es natürlich.
Taylor Edmiston

1
In Python 3.6+ -Wörterbüchern wird die Einfügereihenfolge beibehalten. Dies ist natürlich nicht dasselbe wie die Möglichkeit, sie nach Wert zu sortieren, aber andererseits ist es nicht mehr gültig zu sagen, dass "die Wörterbuchdatenstruktur keine inhärente Reihenfolge hat".
Konrad Kocik

Antworten:


4949

Python 3.6+

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
{k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

Ältere Python

Es ist nicht möglich, ein Wörterbuch zu sortieren, sondern nur eine Darstellung eines sortierten Wörterbuchs zu erhalten. Wörterbücher sind von Natur aus ordentlich, 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_xwird 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 anstatt 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 können wir verwenden, da das Entpacken nicht erlaubt ist [1]

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

Wenn Sie die Ausgabe als Diktat wünschen, können Sie Folgendes verwenden collections.OrderedDict:

import collections

sorted_dict = collections.OrderedDict(sorted_x)

43
Für Timings in verschiedenen Wörterbüchern, die nach Wertschemata
Gregg Lind

164
sorted_x.reverse()gibt Ihnen eine absteigende Reihenfolge (durch das zweite Tupel-Element)
sagteimu apale

414
sagteimu: Da wir bereits verwenden sorted(), ist es viel effizienter, das reverse=TrueArgument weiterzugeben .
rmh

121
In Python3 habe ich ein Lambda verwendet : sorted(d.items(), key=lambda x: x[1]). Funktioniert dies in Python 2.x?
Keyo

84
OrderedDict wurde in 2.7 zu Sammlungen hinzugefügt. Sortierbeispiel gezeigt unter: docs.python.org/library/…
monkut

1262

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

Nun, es ist tatsächlich möglich, eine "Sortierung nach Wörterbuchwerten" durchzuführen. Vor kurzem musste ich das in einem Code Golf machen (Stack Overflow Frage Code Golf: Word Frequenzdiagramm ). Kurz gesagt, das Problem war von der Art: Geben Sie bei einem gegebenen Text an, wie oft jedes Wort vorkommt, und zeigen Sie eine Liste der wichtigsten Wörter an, sortiert nach abnehmender Häufigkeit.

Wenn Sie ein Wörterbuch mit den Wörtern als Schlüssel und der Anzahl der Vorkommen jedes Wortes als Wert erstellen, wird dies wie folgt vereinfacht:

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

Anschließend können Sie eine Liste der Wörter abrufen, die nach Verwendungshäufigkeit sorted(d, key=d.get)sortiert sind. Die Sortierung wird über die Wörterbuchschlüssel wiederholt, 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 ausführliche Erklärung, um zu veranschaulichen, was die Leute oft mit "Ich kann ein Wörterbuch leicht nach Schlüssel sortieren, aber wie sortiere ich nach Wert" meinen - und ich denke, der ursprüngliche Beitrag hat versucht, ein solches Problem anzugehen. Die Lösung besteht darin, eine Art Liste der Schlüssel basierend auf den oben gezeigten Werten zu erstellen.


31
Dies ist auch gut, key=operator.itemgetter(1)sollte aber aus Effizienzgründen skalierbarer sein alskey=d.get
smci

3
@raylu Ich beobachte mit itemgetter ein "funktioniert nicht" -Verhalten: ----- from operator import itemgetter d = {"a":7, "b":1, "c":5, "d":3} sorted_keys = sorted(d, key=itemgetter, reverse=True) for key in sorted_keys: print "%s: %d" % (key, d[key]) ----- -> b: 1 c: 5 a: 7 d: 3 Die Ergebnisse ändern sich jedes Mal, wenn ich den Code ausführe: seltsam . (Entschuldigung, ich kann den Code nicht richtig anzeigen lassen)
bli

12
@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True)und for key, val in sorted_keys: print "%s: %d" % (key, val)- itemgetter erstellt eine Funktion, wenn sie aufgerufen wird. Sie verwenden sie nicht direkt wie in Ihrem Beispiel. Und eine einfache Iteration auf einem Diktat verwendet die Schlüssel ohne die Werte
Izkata

18
Ich bin aus der Zukunft gekommen, um Ihnen zu erzählen collections.Counter, welche most_commonMethode Sie interessieren könnte :)
Eevee

2
@Eevee - da ist das Risiko, in nicht-f2f kurzen Kommentaren missverstanden zu werden. Amuzing tidbit: collections.Counterwurde in 2.7 hinzugefügt, das vor fast genau 7 Jahren veröffentlicht wurde! (Ich wusste es damals nicht - und ich hätte es aus
Gründen

857

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.

Um es in absteigender Reihenfolge zu sortieren, fügen Sie einfach hinzu reverse=True:

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

Eingang:

d = {'one':1,'three':3,'five':5,'two':2,'four':4}
a = sorted(d.items(), key=lambda x: x[1])    
print(a)

Ausgabe:

[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]

Nach dem , was ich gesehen habe ( docs.python.org/2/library/… ), gibt es eine Klasse namens OrderedDict, die sortiert werden kann und die Reihenfolge beibehält, während sie noch ein Wörterbuch ist. Aus den Codebeispielen können Sie Lambda verwenden, um es zu sortieren, aber ich habe es nicht persönlich ausprobiert: P
UsAndRufus

53
Ich würde es vorziehen key=lambda (k, v): vpersönlich
Claudiu

35
@Claudiu Ich mag diese (k, v)Syntax auch, aber sie ist in Python 3 nicht verfügbar, wo das Entpacken von Tupelparametern entfernt wurde.
Bob Stein

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

3
Nein. Das Erstellen eines Diktats aus einer sortierten Liste von Tupeln beendet die Bestellung erneut ...
Jean-François Fabre

233

Diktate können nicht sortiert werden, aber Sie können daraus eine sortierte Liste 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))

In welcher Reihenfolge werden Schlüssel mit demselben Wert platziert? Ich habe die Liste zuerst nach Schlüsseln und dann nach Werten sortiert, aber die Reihenfolge der Schlüssel mit demselben Wert bleibt nicht erhalten.
SabreWolfy

1
Dicts können jetzt sortiert werden, beginnend mit CPython 3.6 und allen anderen Python-Implementierungen, beginnend mit 3.7
Boris

161

In Python 2.7 haben wir den neuen OrderedDict- Typ, der sich an die Reihenfolge erinnert, in der die Elemente 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}

So erstellen Sie ein neu geordnetes Wörterbuch aus dem Original, sortieren 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)])

5
Dies ist nicht das, worum es bei der Frage geht - es geht nicht darum, die Reihenfolge der Schlüssel beizubehalten, sondern um das "Sortieren nach Wert"
Nas Banov

10
@Nas Banov: Es wird NICHT nach dem Schlüssel sortiert. Es wird in der Reihenfolge sortiert, wir erstellen die Artikel. In unserem Fall sortieren wir nach dem Wert. Leider wurde das 3-Punkte-Diktat leider so gewählt, dass die Reihenfolge dieselbe war, wenn es nach Wert und Schlüssel sortiert wurde. Deshalb habe ich das Beispiel-Diktat erweitert.
Mykhal

sorted(d.items(), key=lambda x: x[1])Können Sie erklären, was das xbedeutet, warum es x[1]Lambda dauern kann ? Warum kann es nicht sein x[0]? Vielen Dank!
JZAU

1
@Boern d.items()gibt einen listenartigen Container mit (key, value)Tupeln zurück. [0]greift auf das erste Element des Tupels - den Schlüssel - und [1]auf das zweite Element - den Wert - zu.
BallpointBen

2
Hinweis: Ab 3.6 (als CPython / PyPy Implementierung Detail) und als von 3,7 (als Garantie Python - Sprache), plain dictist Einfügung auch bestellt haben , so können Sie einfach ersetzen können OrderedDictmit dictfür Code auf dem modernen Python. OrderedDictwird nicht mehr wirklich benötigt, es sei denn, Sie müssen die Reihenfolge eines vorhandenen dict(mit move_to_end/ popitem) neu ordnen oder Gleichheitsvergleiche benötigen, um auftragsabhängig zu sein. Es verbraucht viel mehr Speicher als normal dict. Wenn Sie also können, dictist dies der richtige Weg.
ShadowRanger

104

UPDATE: 5. DEZEMBER 2015 mit Python 3.5

Während ich die akzeptierte Antwort nützlich gefunden, ich war überrascht, dass es zu Referenz nicht aktualisiert wurde OrderedDict aus der Standardbibliothek Sammlungen Modul als eine tragfähige, moderne Alternative - entwickelt , 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)])

Die offizielle OrderedDict- Dokumentation bietet ebenfalls ein sehr ähnliches Beispiel, verwendet jedoch 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)])

86

Ziemlich genau wie die Antwort von Hank Gay :

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

9
..und wie bei Hank Gay's Antwort brauchen Sie die eckigen Klammern nicht. sortiert () nimmt gerne alle iterierbaren Elemente an, z. B. einen Generatorausdruck.
John Fouhy

Möglicherweise müssen Sie die Tupelelemente (Wert, Schlüssel) noch austauschen, um das Element (Schlüssel, Wert) zu erhalten. Ein weiteres Listenverständnis ist dann erforderlich. [(key, value) for (value, key) in sorted_list_of_tuples]
sagteimu apale

Nein, es ist besser, eckige Klammern zu lassen, da sorteddie Liste ohnehin neu erstellt werden muss und die Neuerstellung von gencomp schneller erfolgt. Gut für Codegolf, schlecht für Geschwindigkeit. Behalte die hässliche ([])Version.
Jean-François Fabre

75

Es kann oft sehr praktisch sein, namedtuple zu verwenden . Sie haben beispielsweise ein Wörterbuch mit 'Name' als Schlüssel 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}

Sortieren 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 des zweitbesten Spielers (Index = 1) ermitteln, der sehr pythonisch so aussieht:

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

Wie könnte ich es wieder in ein Wörterbuch konvertieren?
Rowana

as_list = [Spieler (v, k) für (k, v) in d.items ()] as_dict = dict ((p.name, p.score) für p in as_list)
Remi

72

Ab Python 3.6 wird das eingebaute Diktat bestellt

Gute Nachrichten, daher sollte der ursprüngliche Anwendungsfall des OP für die Zuordnung von Paaren, die aus einer Datenbank mit eindeutigen Zeichenfolgen-IDs als Schlüssel und numerischen Werten als Werte in einem integrierten Python v3.6 + -Dikt abgerufen wurden, jetzt die Einfügereihenfolge berücksichtigen.

Wenn Sie sagen, die resultierenden zwei Spaltentabellenausdrücke aus einer Datenbankabfrage wie:

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 durch numerischen Index und natürlich mit der gleichen Länge), dann:

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)

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

foo 0
bar 1
baz 42

in der gleichen Reihenfolge pro Wert von v.

Wo in der Python 3.5-Installation auf meinem Computer derzeit Folgendes angezeigt wird:

bar 1
foo 0
baz 42

Einzelheiten:

Wie 2012 von Raymond Hettinger vorgeschlagen (vgl. Mail zu Python-Dev mit dem Betreff "Kompaktere Wörterbücher mit schnellerer Iteration" ) und jetzt (2016) in einer Mail von Victor Stinner an Python-Dev mit Betreff "Python 3.6 dict wird kompakt und erhält eine private Version; und Schlüsselwörter werden " aufgrund der Korrektur / Implementierung des Problems 27350 " Kompaktes und geordnetes Diktat " in Python 3.6 geordnet. Wir können jetzt ein eingebautes Diktat verwenden, um die Einfügereihenfolge aufrechtzuerhalten !!

Hoffentlich führt dies als ersten Schritt zu einer dünnen OrderedDict-Implementierung. Wie @ JimFasarakis-Hilliard angedeutet hat, sehen einige auch in Zukunft Anwendungsfälle für den OrderedDict-Typ. Ich denke, die Python-Community im Allgemeinen wird sorgfältig prüfen, ob dies den Test der Zeit bestehen wird und wie die nächsten Schritte aussehen werden.

Zeit, unsere Codierungsgewohnheiten zu überdenken, um die Möglichkeiten nicht zu verpassen, die sich aus einer stabilen Reihenfolge von:

  • Schlüsselwortargumente und
  • (Zwischen-) Diktspeicherung

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

Das zweite, da es dazu anregt, dicts leichter als Zwischenspeicher in Verarbeitungspipelines zu verwenden.

Raymond Hettinger stellte freundlicherweise eine Dokumentation zur Verfügung, in der " The Tech Behind Python 3.6 Dictionaries " erläutert wurde - aus seiner Präsentation der San Francisco Python Meetup Group 2016-DEC-08.

Und vielleicht erhalten einige hochdekorierte Fragen- und Antwortseiten mit Stapelüberlauf Varianten dieser Informationen, und viele qualitativ hochwertige Antworten erfordern auch ein Update pro Version.

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

Wie @ajcr zu Recht bemerkt: "Der auftragserhaltende Aspekt dieser neuen Implementierung wird als Implementierungsdetail betrachtet und sollte nicht als verlässlich angesehen werden." (aus dem whatsnew36 ) nicht nit picking, aber das zitat wurde etwas pessimistisch geschnitten ;-). Es wird fortgesetzt als "(dies kann sich in Zukunft ändern, es ist jedoch erwünscht, diese neue Dikt-Implementierung für einige Releases in der Sprache zu haben, bevor die Sprachspezifikation geändert wird, um eine auftragserhaltende Semantik für alle aktuellen und zukünftigen Python-Implementierungen vorzuschreiben; dies auch hilft dabei, die Abwärtskompatibilität mit älteren Versionen der Sprache zu erhalten, in denen die zufällige Iterationsreihenfolge noch gültig ist, z. B. Python 3.5). "

Wie in einigen menschlichen Sprachen (z. B. Deutsch) prägt der Gebrauch die Sprache, und der Wille wurde jetzt erklärt ... in whatsnew36 .

Update 15.12.2017:

In einer Mail an die Python-Entwicklerliste erklärte Guido van Rossum:

Mach es so. "Dikt hält Einfügereihenfolge" ist das Urteil. Vielen Dank!

Der CPython-Nebeneffekt der Diktateinfügungsreihenfolge in Version 3.6 wird nun Teil der Sprachspezifikation (und nicht mehr nur ein Implementierungsdetail). Dieser Mail-Thread tauchte auch einige markante Designziele auf collections.OrderedDict, an die Raymond Hettinger während der Diskussion erinnerte.


15
Die Warnung auf der Seite 'Whatsnew', auf die Sie verlinkt haben, sollte hervorgehoben werden: Der auftragserhaltende Aspekt dieser neuen Implementierung wird als Implementierungsdetail betrachtet und sollte nicht als verlässlich angesehen werden . Niemand sollte davon ausgehen, dass der dictTyp die Einfügereihenfolge in seinem Code berücksichtigt. Dies ist nicht Teil der Sprachdefinition und die Implementierung könnte sich in zukünftigen Versionen ändern. Verwenden Sie weiter, OrderedDictum die Bestellung zu garantieren.
Alex Riley

@ajcr danke für die Einschränkung, sehr geschätzt - da Smileys und vielleicht in meine Antwort eingewoben wurden, sollten diese darauf hinweisen, dass die Änderung massiv ist, aber natürlich nur für CPython (Referenzimplementierung) und PyPy verfügbar ist. Für etwas völlig anderes ... Ich spreche selten mit Details, die nicht implementiert sind, wenn ich Mensch-Maschine-Anweisungen codiere. Wenn es nur Jython gewesen wäre ;-) ... Ich hätte vielleicht nicht den Mut gehabt, es zu schreiben.
Dilettant

OrderedDictwird definitiv nicht fallen gelassen; Stattdessen wird es zu einem dünnen Wrapper um die aktuelle Diktatimplementierung (Sie können also hinzufügen, dass es auch kompakter wird). Das Hinzufügen dieses Snippets mit dem ImportErrorist nicht ganz die beste Idee, da es Leser irreführt, OrderedDictdie keinen Nutzen haben.
Dimitris Fasarakis Hilliard

@ JimFasarakis-Hilliard danke für das Feedback. "Ganz beste Ideen" haben mich zum Lächeln gebracht - die Zukunft ist oft schwer vorherzusagen. Aber ich mag Ihren Vorschlag, die Quellen zu überprüfen, es zu versuchen und dann die Antwort entsprechend zu aktualisieren. Danke noch einmal.
Dilettant

8
@AlexRiley Diese Einschränkung ist nicht mehr korrekt. Python3.7 garantiert geordnete Wörterbücher.
Gerrit

42

Ich hatte das gleiche Problem und habe es folgendermaßen 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 bedeutet "Ich kann nach den Schlüsseln sortieren, aber wie kann ich nach den Werten sortieren?" Klar, dass er eine Liste von möchte die Schlüssel sortiert nach dem Wert ihrer Werte.)

Bitte beachten Sie, dass die Reihenfolge nicht genau definiert ist (Schlüssel mit demselben Wert werden in der Ausgabeliste in einer beliebigen Reihenfolge angezeigt).


1
Sie vermissen den Wert aus dem Ergebnis
Dejell

Beachten Sie, dass Sie sowohl das Wörterbuch iterieren als auch Werte anhand ihres Schlüssels abrufen. In Bezug auf die Leistung ist dies keine optimale Lösung.
Ron Klein

1
@Dejell: Wie der Mitwirkende sagt, interpretiert er die Frage als "Kann ich die Liste der Schlüssel nach den Werten sortieren lassen". Wir brauchen die Werte im Ergebnis nicht, wir haben sie im Wörterbuch.
Max

36

Wenn die Werte numerisch sind, können Sie sie auch Counteraus Sammlungen verwenden .

from collections import Counter

x = {'hello': 1, 'python': 5, 'world': 3}
c = Counter(x)
print(c.most_common())

>> [('python', 5), ('world', 3), ('hello', 1)]    

Was ist, wenn Ihr Wörterbuch >>> x = {'Hallo': 1, 'Python': 5, 'Welt': 300} ist
James Sapam

@yopy Counter({'hello':1, 'python':5, 'world':300}).most_common()gibt [('world', 300), ('python', 5), ('hello', 1)]. Dies funktioniert tatsächlich für jeden sortierbaren Werttyp (obwohl viele andere Zähleroperationen erfordern, dass Werte mit Ints vergleichbar sind).
lvc

34

Führen Sie in Python 2.7 einfach Folgendes aus:

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

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

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

Kopieren und Einfügen von: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

Genießen ;-)


25

Dies ist der Code:

import operator
origin_list = [
    {"name": "foo", "rank": 0, "rofl": 20000},
    {"name": "Silly", "rank": 15, "rofl": 1000},
    {"name": "Baa", "rank": 300, "rofl": 20},
    {"name": "Zoo", "rank": 10, "rofl": 200},
    {"name": "Penguin", "rank": -1, "rofl": 10000}
]
print ">> Original >>"
for foo in origin_list:
    print foo

print "\n>> Rofl sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
    print foo

print "\n>> Rank sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rank")):
    print foo

Hier sind die Ergebnisse:

Original

{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}

Rofl

{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}

Rang

{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}

25

Versuchen Sie den folgenden Ansatz. Definieren wir ein Wörterbuch namens mydict mit den folgenden Daten:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

Wenn man das Wörterbuch nach Schlüsseln sortieren möchte, kann man so etwas tun:

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

Dies sollte die folgende Ausgabe zurückgeben:

alan: 2
bob: 1
carl: 40
danny: 3

Wenn man dagegen ein Wörterbuch nach Wert sortieren möchte (wie in der Frage gestellt), kann man Folgendes tun:

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

Das Ergebnis dieses Befehls (Sortieren des Wörterbuchs nach Wert) sollte Folgendes zurückgeben:

bob: 1
alan: 2
danny: 3
carl: 40

Genial! for key, value in sorted(mydict.iteritems(), key=lambda (k,v): v["score"]):ermöglicht es Ihnen, nach einem Unterschlüssel zu sortieren
Andomar

es gibt mir Syntaxfehler in der Nähe von Lambda in Python3
Suleman Elahi

21

Ab Python 3.6 werden dictObjekte nun nach Einfügereihenfolge sortiert. Es ist 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}

Vorher musste man verwenden OrderedDict.

In der Python 3.7-Dokumentation heißt es:

In Version 3.7 geändert: Die Wörterbuchreihenfolge ist garantiert die Einfügereihenfolge. Dieses Verhalten war ein Implementierungsdetail von CPython aus Version 3.6.


funktioniert super! dict(sorted(words.items(), key=lambda x: x[1], reverse=True))für DESC
vizyourdata

20

Sie können auch einen "invertierten Index" erstellen

from collections import defaultdict
inverse= defaultdict( list )
for k, v in originalDict.items():
    inverse[v].append( k )

Jetzt hat Ihre Umkehrung die Werte; Jeder Wert enthält eine Liste der zutreffenden Schlüssel.

for k in sorted(inverse):
    print k, inverse[k]

19

Sie können die Sammlungen verwenden . Beachten Sie, dass dies sowohl für numerische als auch für nicht numerische Werte funktioniert.

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

7
Wie unterscheidet sich das von Ivan Sas Antwort ?
Peter Mortensen

15

Sie können ein Sprungdiktat verwenden, bei dem es sich um ein Wörterbuch handelt, das permanent nach Wert sortiert ist.

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

Wenn Sie verwenden keys(), values()oder items()dann iterieren Sie in sortierter Reihenfolge nach Wert.

Es wird mithilfe der Überspringlisten- Datenstruktur implementiert.


Können wir die Reihenfolge der Sortierung ändern? Im Moment ist es aufsteigend, aber ich möchte absteigend.
Suleman Elahi

afaik müssten Sie Ihre Werte negieren, um die Reihenfolge umzukehren
malthe

Wow, ich denke nicht so ... danke.
Suleman Elahi

14

Sie können auch eine benutzerdefinierte Funktion verwenden, die an den Schlüssel übergeben werden kann.

def dict_val(x):
    return x[1]
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=dict_val)

12
from django.utils.datastructures import SortedDict

def sortedDictByKey(self,data):
    """Sorted dictionary order by key"""
    sortedDict = SortedDict()
    if data:
        if isinstance(data, dict):
            sortedKey = sorted(data.keys())
            for k in sortedKey:
                sortedDict[k] = data[k]
    return sortedDict

2
Die Frage war: Nach Wert sortieren, nicht nach Tasten ... Ich sehe gerne eine Funktion. Sie können Sammlungen importieren und natürlich sortiert (data.values ​​()) verwenden
Remi

10

Wie Dilettant betont hat , behält Python 3.6 jetzt die Reihenfolge bei ! Ich dachte, ich würde eine Funktion teilen, die ich geschrieben habe und die das Sortieren einer iterierbaren Funktion (Tupel, Liste, Diktat) erleichtert. Im letzteren Fall können Sie entweder nach Schlüsseln oder Werten sortieren und den numerischen Vergleich berücksichtigen. Nur für> = 3.6!

Wenn Sie versuchen, sortiert auf einem Iterable zu verwenden, das z. B. Zeichenfolgen und Ints enthält, schlägt sorted () fehl. Natürlich können Sie den String-Vergleich mit str () erzwingen. In einigen Fällen möchten Sie jedoch einen tatsächlichen numerischen Vergleich durchführen, der 12kleiner als ist 20(was beim Zeichenfolgenvergleich nicht der Fall ist). Also habe ich mir folgendes ausgedacht. Wenn Sie einen expliziten numerischen Vergleich wünschen, können Sie das Flag verwenden, num_as_numdas versucht, eine explizite numerische Sortierung durchzuführen, indem versucht wird, alle Werte in Gleitkommazahlen zu konvertieren. Wenn dies erfolgreich ist, wird eine numerische Sortierung durchgeführt, andernfalls wird auf einen Zeichenfolgenvergleich zurückgegriffen.

Kommentare zur Verbesserung oder Push-Anfragen sind willkommen.

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")

9

Hier ist eine Lösung mit zip on d.values()undd.keys() . Ein paar Zeilen weiter unten auf diesem Link (in Dictionary-Ansichtsobjekten) steht:

Dies ermöglicht die Erstellung von (Wert-, Schlüssel-) Paaren mit zip (): pair = zip (d.values ​​(), d.keys ()).

Wir können also Folgendes tun:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]

9

Denken Sie natürlich daran, dass Sie verwenden müssen, OrderedDictda normale Python-Wörterbücher nicht die ursprüngliche Reihenfolge beibehalten.

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))

Wenn Sie nicht über Python 2.7 oder höher verfügen, können Sie die Werte in einer Generatorfunktion am besten durchlaufen. (Es gibt einen OrderedDictfür 2.4 und 2.6 hier , aber

a) Ich weiß nicht, wie gut es funktioniert

und

b) Sie müssen es natürlich herunterladen und installieren. Wenn Sie keinen Administratorzugriff haben, ist die Option leider nicht verfügbar.)


def gen(originalDict):
    for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

Sie können auch jeden Wert ausdrucken

for bleh, meh in gen(myDict):
    print(bleh, meh)

Bitte denken Sie daran, die Klammern nach dem Drucken zu entfernen, wenn Sie Python 3.0 oder höher nicht verwenden


Normale Python-Wörterbücher behalten nicht die ursprüngliche Reihenfolge bei - ab Python 3.7.
Gerrit

7

Verwenden Sie ValueSortedDict aus dicts :

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

6

Dies funktioniert in 3.1.x:

import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)

6

Ich habe gerade relevante Fähigkeiten von Python für alle gelernt .

Sie können eine temporäre Liste verwenden, um das Wörterbuch zu sortieren:

#Assume dictionary to be:
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}

# create a temporary list
tmp = []

# iterate through the dictionary and append each tuple into the temporary list 
for key, value in d.items():
    tmptuple = (value, key)
    tmp.append(tmptuple)

# sort the list in ascending order
tmp = sorted(tmp)

print (tmp)

Wenn Sie die Liste in absteigender Reihenfolge sortieren möchten, ändern Sie einfach die ursprüngliche Sortierzeile in:

tmp = sorted(tmp, reverse=True)

Unter Verwendung des Listenverständnisses wäre der eine Liner:

#Assuming the dictionary looks like
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
#One liner for sorting in ascending order
print (sorted([(v, k) for k, v in d.items()]))
#One liner for sorting in descending order
print (sorted([(v, k) for k, v in d.items()], reverse=True))

Beispielausgabe:

#Asending order
[(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')]
#Descending order
[(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]

Dies ist das Sortieren nach Schlüsseln, nicht nach Werten.
Rubel

Wenn Sie es im ursprünglichen Format drucken möchten, sollten Sie Folgendes tun: print ([(k, v) für v, k in sortiert ([(v, k) für k, v in d.items ()])). Die Ausgabe ist: [('orange', 1,0), ('Apfel', 500,1), ('Ananas', 789,0), ('Banane', 1500,2)]. Mit [(k, v) für v, k in sortiert ([(v, k) für k, v in d.items ()], reverse = True)] lautet die Ausgabe: [('banana', 1500.2), ("Ananas", 789,0), ("Apfel", 500,1), ("Orange", 1,0)]
Hermes Morales

5

Durchlaufen Sie ein Diktat und sortieren Sie es nach seinen Werten in absteigender Reihenfolge:

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1

5

Wenn Ihre Werte Ganzzahlen sind und Sie Python 2.7 oder höher verwenden, können Sie collections.Counterstattdessen anstelle von verwenden dict. Die most_commonMethode gibt Ihnen alle Elemente, sortiert nach dem Wert.


5

Der Vollständigkeit halber veröffentliche ich eine Lösung mit heapq . Beachten Sie, dass diese Methode sowohl für numerische als auch für nicht numerische Werte funktioniert

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> x_items = x.items()
>>> heapq.heapify(x_items)
>>> #To sort in reverse order
>>> heapq.nlargest(len(x_items),x_items, operator.itemgetter(1))
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> heapq.nsmallest(len(x_items),x_items, operator.itemgetter(1))
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

4

Aufgrund der Anforderungen an die Abwärtskompatibilität mit älteren Versionen von Python halte ich die OrderedDict-Lösung für sehr unklug. Sie möchten etwas, das mit Python 2.7 und älteren Versionen funktioniert.

Die in einer anderen Antwort erwähnte Sammlungslösung ist jedoch absolut hervorragend, da Sie eine Verbindung zwischen Schlüssel und Wert neu trainieren, was bei Wörterbüchern äußerst wichtig ist.

Ich bin mit der ersten Wahl in einer anderen Antwort nicht einverstanden, weil sie die Schlüssel wegwirft.

Ich habe die oben erwähnte Lösung verwendet (Code unten gezeigt) und den Zugriff auf Schlüssel und Werte beibehalten. In meinem Fall lag die Reihenfolge bei den Werten, aber die Wichtigkeit war die Reihenfolge der Schlüssel nach der Bestellung der Werte.

from collections import Counter

x = {'hello':1, 'python':5, 'world':3}
c=Counter(x)
print c.most_common()


>> [('python', 5), ('world', 3), ('hello', 1)]
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.