sortieren - sort dictionary python 3 by key




Wie sortiere ich ein Wörterbuch nach Wert? (20)

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

Ich kann nach Schlüsseln sortieren, aber wie kann ich anhand der Werte sortieren?

Hinweis: Ich habe die Stack Overflow-Frage gelesen. Wie sortiere ich eine Liste von Wörterbüchern nach den Werten des Wörterbuchs in Python? und könnte wahrscheinlich meinen Code ändern, um eine Liste von Wörterbüchern zu haben, aber da ich eigentlich keine Liste von Wörterbüchern brauche, wollte ich wissen, ob es eine einfachere Lösung gibt.


Ab Python 3.6 werden die eingebauten Diktaturen bestellt

Gute Nachrichten, so dass der ursprüngliche Anwendungsfall des OPs von Mapping-Paaren, die aus einer Datenbank mit eindeutigen String-IDs als Schlüssel und numerischen Werten als Werte in einem integrierten Python v3.6 + -Dict abgerufen wurden, nun die Einfügereihenfolge berücksichtigen sollte.

Wenn die aus einer Datenbankabfrage resultierenden zwei Spaltentabellenausdrücke wie folgt aussehen:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

würde in zwei Python-Tupeln gespeichert, k_seq und v_seq (ausgerichtet durch numerischen Index und mit der gleichen Länge natürlich), dann:

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

Ausgabe später erlauben als:

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

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

foo 0
bar 1
baz 42

in der gleichen Reihenfolge pro Wert von v.

Wo in der Python 3.5-Installation auf meinem Rechner aktuell Folgendes ausgegeben wird:

bar 1
foo 0
baz 42

Einzelheiten:

Wie 2012 von Raymond Hettinger vorgeschlagen (vgl. Mail über Python-Dev mit Betreff "Kompaktere Wörterbücher mit schnellerer Wiederholung" ) und nun (2016) in einer Mail von Victor Stinner an Python-Dev mit Betreff "Python 3.6 dict" angekündigt compact und erhält eine private Version; und die Schlüsselwörter werden geordnet " Durch die Korrektur / Implementierung von Ausgabe 27350 " Compact and order dict " in Python 3.6 können wir jetzt die eingebaute Diktatur verwenden, um die Reihenfolge der Einfügung beizubehalten !!

Hoffentlich führt dies als erster Schritt zu einer Thin-OrderedDict-Implementierung. Wie @ JimFasarakis-Hilliard angedeutet hat, sehen manche Anwendungsfälle auch in Zukunft für den OrderedDict-Typ. Ich denke, die gesamte Python-Community wird sorgfältig prüfen, ob dies die Zeit überdauert und wie die nächsten Schritte aussehen werden.

Zeit, unsere Kodierungsgewohnheiten zu überdenken, um die Möglichkeiten nicht zu verpassen, die durch die stabile Anordnung

  • Keyword-Argumente und
  • Zwischenspeicherung

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

Die zweite, da sie die Verwendung von dict als Zwischenspeicher in Verarbeitungsleitungen erleichtert.

Raymond Hettinger hat freundlicherweise eine Dokumentation zur Verfügung gestellt, in der er " The Tech Behind Python 3.6 Wörterbücher " von seiner Präsentation der San Francisco Python Meetup Group 2016-DEC-08 erläutert.

Möglicherweise erhalten einige -hoch gestaltete Frage- und Antwortseiten Varianten dieser Informationen, und viele hochwertige Antworten erfordern auch ein Update pro Version.

Vorbehalt-Entleerer (siehe auch Update 2017-12-15):

Wie @ajcr zu Recht feststellt: "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 der Zukunft ändern, es ist jedoch wünschenswert, diese neue Diktimplementierung für einige Releases in der Sprache zu haben, bevor die Sprachspezifikation geändert wird, um eine bestandserhaltende Semantik für alle aktuellen und zukünftigen Python-Implementierungen zu verlangen; dies auch trägt dazu bei, die Rückwärtskompatibilität mit älteren Versionen der Sprache aufrechtzuerhalten, in der die Reihenfolge der zufälligen Iterationen noch aktiv ist (z. B. Python 3.5). "

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

Update 2017-12-15:

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

Mach es so. "Dict hält Einfügungsreihenfolge" lautet das Urteil. Vielen Dank!

Daher ist der CPython-Nebeneffekt der Version 3.6 der Reihenfolge des Einfügens von Diktieren nun Teil der Sprachspezifikation (und nicht mehr nur ein Implementierungsdetail). Dieser Mail-Thread brachte auch einige herausragende Designziele für collections.OrderedDict zum Vorschein. OrderedDict, wie von Raymond Hettinger in der Diskussion daran erinnert.


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

Nun, es ist tatsächlich möglich, "nach Wörterbuchwerten sortieren" zu tun. Vor kurzem musste ich das in einem Code Golf tun (-Frage Code Golf: Word-Frequenzdiagramm ). Kurz gesagt, das Problem war von der Art: Wenn Sie einen Text erhalten, zählen Sie, wie oft jedes Wort gefunden wird, und zeigen Sie eine Liste der obersten Wörter an, sortiert nach abnehmender Häufigkeit.

Wenn Sie ein Wörterbuch mit den Wörtern als Schlüsseln und der Anzahl der Vorkommen jedes Wortes als Wert erstellen, wird es hier vereinfacht:

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 Verwendungshäufigkeit bei sorted(d, key=d.get) Die Sortierung wird über die Wörterbuchschlüssel wiederholt, wobei die Anzahl der sorted(d, key=d.get) 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 Leute oft mit "Ich kann ein Wörterbuch leicht nach Schlüssel sortieren, aber wie sortiere ich nach Wert" - und ich glaube, das OP hat versucht, ein solches Problem anzugehen. Die Lösung besteht darin, eine Liste der Schlüssel zu erstellen, die auf den Werten basieren, wie oben gezeigt.


Dies gibt die Liste der Schlüssel-Wert-Paare im Wörterbuch zurück, sortiert nach Wert vom höchsten zum niedrigsten Wert:

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

Verwenden Sie für das nach Schlüssel sortierte Wörterbuch Folgendes:

sorted(d.items(), reverse=True)

Die Rückgabe ist eine Liste von Tupeln, da Wörterbücher selbst nicht sortiert werden können.

Dies kann sowohl gedruckt als auch in weitere Berechnungen gesendet werden.


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}

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

$ 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

Es ist nicht möglich, ein Wörterbuch zu sortieren, nur um eine Darstellung eines sortierten Wörterbuchs zu erhalten. Wörterbücher sind von Natur aus ohne Ordnung, andere Typen wie Listen und Tupel jedoch nicht. Sie benötigen also einen geordneten Datentyp, um sortierte Werte darzustellen, die eine Liste sind - 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 ist eine Liste von Tupeln, sortiert nach dem zweiten Element in jedem Tupel. 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 ist das Auspacken nicht erlaubt [1]

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

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 die Dinge nach Wert zu sortieren und in einer Variablen, in diesem Fall mit dem ursprünglichen Wörterbuch, verarbeitet, zu speichern.

Hoffentlich hilft das!


Hier ist eine Lösung, die zip für d.values() und d.keys() . Ein paar Zeilen weiter unten (auf Dictionary-Ansichtsobjekte) lautet:

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

So können wir 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')]

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

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

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

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


In Python 2.7 machen Sie einfach:

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-Einfügen aus: http://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

Genießen ;-)


Sie können auch eine benutzerdefinierte Funktion verwenden, die an key ü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)

Eine weitere Möglichkeit ist die Verwendung der Labmda-Funktion

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

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 )

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

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

Sie können die sortierte Funktion von Python verwenden

sorted(iterable[, cmp[, key[, reverse]]])

So können Sie verwenden:

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

Besuchen Sie diesen Link für weitere Informationen zur sortierten Funktion: https://docs.python.org/2/library/functions.html#sorted


Sie können ein Überspringdikt verwenden , ein Wörterbuch, 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 keys() , values() oder items() Sie nach Wert sortiert.

Es wird mithilfe der Datenstruktur für die Überspringliste implementiert.


Versuchen Sie den folgenden Ansatz. Lassen Sie uns ein Wörterbuch namens mydict mit den folgenden Daten definieren:

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

Wenn Sie das Wörterbuch nach Schlüsseln sortieren möchten, können Sie Folgendes 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 Sie dagegen ein Wörterbuch nach Wert sortieren möchten (wie in der Frage gestellt), können Sie 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

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

Ziemlich das gleiche wie die Antwort von Hank Gay;

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

Oder ein bisschen optimiert, wie von John Fouhy vorgeschlagen;

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


UPDATE: 5. DEZEMBER 2015 mit Python 3.5

Obwohl ich die akzeptierte Antwort für nützlich hielt, war ich auch überrascht, dass sie nicht aktualisiert wurde, um auf OrderedDict aus dem Standardbibliotheksammlungsmodul als praktikable, moderne Alternative zu verweisen. OrderedDict 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 OrderedDict :

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

Denken Sie daran, dass Sie diese Option verwenden müssen, OrderedDictda normale Python-Wörterbücher die ursprüngliche Reihenfolge nicht 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 eine OrderedDict für 2.4 und 2.6 here , aber

a) I don't know about how well it works 

und

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)
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)

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


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





dictionary