Bei einem Wörterbuch wie diesem:
my_map = {'a': 1, 'b': 2}
Wie kann man diese Karte umkehren, um zu erhalten:
inv_map = {1: 'a', 2: 'b'}
python
dictionary
mapping
reverse
Brian M. Hunt
quelle
quelle
my_map.items()
funktioniert das auchThe order-preserving aspect of this new implementation is considered an implementation detail and should not be relied upon
. Es gibt keine Garantie dafür, dass dies auch so bleibt. Schreiben Sie also keinen Code, der aufDict
dem gleichen Verhalten wie basiertOrderedDict
.Angenommen, die Werte im Diktat sind eindeutig:
quelle
iteritems()
Ausgabe, die ausgegeben werden soll. Daher kann davon ausgegangen werden, dass ein beliebiger Schlüssel für einen nicht eindeutigen Wert zugewiesen wird, der unter bestimmten Bedingungen anscheinend reproduzierbar ist, im Allgemeinen jedoch nicht.iteritems()
Methode mehr gibt und dieser Ansatz nicht funktioniert. Verwenden Sieitems()
es stattdessen wie in der akzeptierten Antwort gezeigt. Ein Wörterbuchverständnis würde dies auch schöner machen als das Aufrufendict
.Wenn die Werte in
my_map
nicht eindeutig sind:quelle
inv_map.get(v, [])
gibt die bereits hinzugefügte Liste zurück, falls vorhanden, sodass die Zuordnung nicht auf eine leere Liste zurückgesetzt wird.setdefault
wäre aber immer noch schöner.inv_map.setdefault(v, set()).add(k)
.my_map.items()
anstelle vonmy_map.iteritems()
.So behalten Sie den Typ Ihres Mappings bei (vorausgesetzt, es handelt sich um eine
dict
oder einedict
Unterklasse):quelle
Versuche dies:
(Beachten Sie, dass die Python-Dokumente in Wörterbuchansichten dies ausdrücklich garantieren
.keys()
und.values()
ihre Elemente in derselben Reihenfolge haben, sodass der oben beschriebene Ansatz funktioniert.)Alternative:
oder mit dem Diktatverständnis von Python 3.0
quelle
Ein anderer, funktionalerer Weg:
quelle
filter
undmap
sollte sterben und in Listenverständnisse subsumiert werden, nicht mehr Varianten wachsen lassen".dict
mit anderen Mapping-Typen wiecollections.OrderedDict
odercollections.defaultdict
Dies erweitert die Antwort von Robert und gilt für den Fall, dass die Werte im Diktat nicht eindeutig sind.
Die Implementierung ist insofern eingeschränkt, als Sie nicht
reversed
zweimal verwenden und das Original zurückerhalten können. Es ist als solches nicht symmetrisch. Es wird mit Python 2.6 getestet. Hier ist ein Anwendungsfall, wie ich das resultierende Diktat drucke.Wenn Sie lieber a
set
als a verwendenlist
möchten und möglicherweise ungeordnete Anwendungen vorhanden sind, für die dies sinnvoll ist, anstatt sie zusetdefault(v, []).append(k)
verwendensetdefault(v, set()).add(k)
.quelle
revdict.setdefault(v, set()).add(k)
set
. Es ist der intrinsische Typ, der hier gilt. Was ist, wenn ich alle Schlüssel finden möchte, bei denen die Werte nicht1
oder sind2
? Dann kann ich einfachd.keys() - inv_d[1] - inv_d[2]
(in Python 3)Wir können ein Wörterbuch mit doppelten Schlüsseln auch umkehren, indem wir
defaultdict
:Siehe hier :
quelle
Zum Beispiel haben Sie das folgende Wörterbuch:
Und du willst es in einer so umgekehrten Form bekommen:
Erste Lösung . Verwenden Sie zum Invertieren von Schlüssel-Wert- Paaren in Ihrem Wörterbuch einen
for
-loop-Ansatz:Zweite Lösung . Verwenden Sie einen Wörterbuchverständnisansatz für die Inversion:
Dritte Lösung . Verwenden Sie das Zurücksetzen des Inversionsansatzes (basiert auf der zweiten Lösung):
quelle
dict
ist reserviert und sollte nicht für Variablennamen verwendet werdenmy_map
istdictio()
? Meinten Siedict()
?Kombination aus Listen- und Wörterbuchverständnis. Kann doppelte Schlüssel verarbeiten
quelle
Wenn die Werte nicht eindeutig sind und Sie ein wenig Hardcore sind:
Beachten Sie insbesondere bei einem großen Diktat, dass diese Lösung weitaus weniger effizient ist als die Antwort Python, die ein Mapping umkehrt / umkehrt, da es
items()
mehrere Schleifen durchläuft.quelle
-1
weil es immer noch die Frage beantwortet, nur meine Meinung.Zusätzlich zu den anderen oben vorgeschlagenen Funktionen, wenn Sie Lambdas mögen:
Oder Sie könnten es auch so machen:
quelle
Ich denke, der beste Weg, dies zu tun, besteht darin, eine Klasse zu definieren. Hier ist eine Implementierung eines "symmetrischen Wörterbuchs":
Lösch- und Iterationsmethoden sind bei Bedarf einfach zu implementieren.
Diese Implementierung ist weitaus effizienter als das Invertieren eines gesamten Wörterbuchs (was auf dieser Seite die beliebteste Lösung zu sein scheint). Ganz zu schweigen davon, dass Sie Ihrem SymDict beliebig viele Werte hinzufügen oder daraus entfernen können, und Ihr inverses Wörterbuch bleibt immer gültig - dies gilt nicht, wenn Sie das gesamte Wörterbuch einfach einmal umkehren.
quelle
dictresize
, aber dieser Ansatz verweigert Python diese Möglichkeit.Dies behandelt nicht eindeutige Werte und behält einen Großteil des Aussehens des eindeutigen Gehäuses bei.
Für Python 3.x, ersetzen
itervalues
mitvalues
.quelle
Die Funktion ist für Werte der Typliste symmetrisch. Tupel werden in Listen verdeckt, wenn reverse_dict (reverse_dict (Wörterbuch)) ausgeführt wird.
quelle
Da Wörterbücher im Gegensatz zu Werten einen eindeutigen Schlüssel im Wörterbuch benötigen, müssen wir die umgekehrten Werte an eine Sortierliste anhängen, die in den neuen spezifischen Schlüsseln enthalten sein soll.
quelle
Schnelle funktionale Lösung für nicht-bijektive Karten (Werte nicht eindeutig):
Theoretisch sollte dies schneller sein als das Hinzufügen zur Menge (oder das Anhängen an die Liste) nacheinander, wie in der imperativen Lösung .
Leider müssen die Werte sortierbar sein, die Sortierung wird von groupby benötigt.
quelle
n
Elemente im ursprünglichen Diktat ist Ihr AnsatzO(n log n)
zeitlich komplex, da die Elemente des Diktats sortiert werden müssen, während der naive imperative AnsatzO(n)
zeitlich komplex ist. Soweit ich weiß, ist Ihr Ansatz vielleicht schneller, bis erdict
in der Praxis absurd groß ist , aber theoretisch ist er sicherlich nicht schneller.Versuchen Sie dies für Python 2.7 / 3.x.
quelle
Ich würde es so in Python 2 machen.
quelle
dict.items
(oderiteritems
in Python 2) ist effizienter als das separate Extrahieren jedes Werts beim Iterieren von Schlüsseln.Dies liefert folgende Ausgabe: {1: ['a', 'd'], 2: ['b'], 3: ['c']}
quelle
dict.items
(oderiteritems
in Python 2) ist effizienter als das separate Extrahieren jedes Werts beim Iterieren von Schlüsseln. Außerdem haben Sie einer Antwort, die andere dupliziert, keine Erklärung hinzugefügt.Dieser Code gefällt so:
quelle
Nicht etwas ganz anderes, nur ein bisschen umgeschriebenes Rezept aus dem Kochbuch. Es wird weiter optimiert, indem die
setdefault
Methode beibehalten wird, anstatt sie jedes Mal durch die Instanz zu bringen:Entwarf, unter CPython 3.x ausgeführt zu werden, für 2.x zu ersetzen
mapping.items()
durchmapping.iteritems()
Auf meinem Computer läuft etwas schneller als andere Beispiele hier
quelle
dict
zu erstellen und am Ende in die gewünschte Klasse zu konvertieren (anstatt mit einer Klasse des richtigen Typs zu beginnen), scheint mir hier einen völlig vermeidbaren Leistungseinbruch zu verursachen.Ich habe dies mit Hilfe von Zyklus 'für' und Methode '.get ()' geschrieben und den Namen 'Karte' des Wörterbuchs in 'Karte1' geändert, weil 'Karte' eine Funktion ist.
quelle
Wenn die Werte nicht eindeutig sind UND ein Hash sein kann (eine Dimension):
Und mit einer Rekursion, wenn Sie tiefer graben müssen als nur eine Dimension:
quelle
{"foo": "bar"}
zu{'b': ['foo'], 'a': ['foo'], 'r': ['foo']}
und löst eine Ausnahme aus, wenn ein Wert inmyDict
nicht iterierbar ist. Ich bin mir nicht sicher, welches Verhalten Sie hier implementieren wollten, aber was Sie tatsächlich implementiert haben, wird so ziemlich niemand wollen.