Flatten verschachtelten dictionaries komprimiert Schlüssel
Angenommen, Sie haben ein Wörterbuch wie:
{'a': 1,
'c': {'a': 2,
'b': {'x': 5,
'y' : 10}},
'd': [1, 2, 3]}
Wie würden Sie gehen über die Abflachung, die in etwas wie:
{'a': 1,
'c_a': 2,
'c_b_x': 5,
'c_b_y': 10,
'd': [1, 2, 3]}
Sie könnten versuchen, zu tun, das Zeug, und wenn es nicht funktioniert, poste den code hier und wir werden Ihnen helfen. Wir werden nicht die Arbeit für dich erledigen 😉
Ich habe meine Antwort in die Antworten Abschnitt, zusammen mit einer Beschreibung der wichtigen Fragen, die anderen Antworten von Ihnen positiv bewertet werden müssen, und die verschiedenen anderen Hinweise und Erklärungen zu den Feinheiten dieses problem.
auch gibt es eine Bibliothek für Sie: github.com/ianlini/flatten-dict
siehe auch: stackoverflow.com/questions/14692690
Ich habe meine Antwort in die Antworten Abschnitt, zusammen mit einer Beschreibung der wichtigen Fragen, die anderen Antworten von Ihnen positiv bewertet werden müssen, und die verschiedenen anderen Hinweise und Erklärungen zu den Feinheiten dieses problem.
auch gibt es eine Bibliothek für Sie: github.com/ianlini/flatten-dict
siehe auch: stackoverflow.com/questions/14692690
InformationsquelleAutor A Timmes | 2011-05-17
Du musst angemeldet sein, um einen Kommentar abzugeben.
Grundsätzlich auf die gleiche Weise würden Sie glätten eine verschachtelte Liste, die Sie gerade zu tun haben, die zusätzliche Arbeit für die Iteration die dict von Schlüssel/Wert, die Schaffung neuer Schlüssel für das neue Wörterbuch und die Erstellung des dictionary im letzten Schritt.
isinstance
mit einemtry..except
blockieren, dies funktioniert für jede Zuordnung, auch wenn es nicht abgeleitetdict
.Geändert es zu testen
collections.MutableMapping
zu machen, mehr generische. Aber für Python < 2.6,try..except
ist wahrscheinlich die beste option.Wenn Sie möchten, leeren Wörterbücher erhalten in der abgeflachten version, die Sie möglicherweise ändern möchten
if isinstance(v, collections.MutableMapping):
zuif v and isinstance(v, collections.MutableMapping):
Beachten Sie, dass
new_key = parent_key + sep + k if parent_key else k
davon ausgegangen, dass die Schlüssel sind immer strings, sonst wird es zu erhöhenTypeError: cannot concatenate 'str' and [other] objects
. Sie können jedoch beheben, indem Sie einfach die Nötigungk
string (str(k)
), oder die Verkettung der Schlüssel in ein Tupel anstatt ein string (Tupel werden kann, dict keys auch).Und das aufblasen der Funktion ist hier
InformationsquelleAutor Imran
Gibt es zwei große überlegungen, dass das original-Plakat zu berücksichtigen:
{'a_b':{'c':1}, 'a':{'b_c':2}}
führen würde{'a_b_c':???}
. Die unter Lösung umgeht das problem durch die Rückkehr einer wiederholenden Paare.joinedKey = '_'.join(*keys)
, das kostet O(N^2) Laufzeit. Allerdings, wenn Sie bereit sind, zu sagennextKey = previousKey+'_'+thisKey
, das bekommt man O(N) Zeit. Die Lösung unten können Sie beides tun (da könnte man nur verketten alle Schlüssel, dann nachbearbeiten).(Leistung ist nicht wahrscheinlich ein Problem, aber werde ich näher auf den zweiten Punkt in Fall, jemand interessiert: Bei der Umsetzung dieser gibt es zahlreiche gefährliche Optionen. Wenn Sie dies tun, rekursiv und Ertrag und die re-Ausbeute, oder alles entspricht berührt Knoten mehr als einmal (das ist ziemlich einfach, versehentlich tun), tun Sie das potentiell O(N^2) statt O(N). Dies ist, weil Sie vielleicht zu berechnen, die einen Schlüssel
a
danna_1
danna_1_i
..., und dann die Berechnunga
danna_1
danna_1_ii
..., aber wirklich Sie sollten nicht zu berechnena_1
wieder. Auch wenn Sie nicht neu berechnen, neu gedeckt, es (a 'level-by-level" - Ansatz) ist genauso schlimm. Ein gutes Beispiel ist zu überlegen, die Leistung auf{1:{1:{1:{1:...(N times)...{1:SOME_LARGE_DICTIONARY_OF_SIZE_N}...}}}}
)Unten ist eine Funktion, die ich schrieb
flattenDict(d, join=..., lift=...)
angepasst werden können für viele Zwecke und können tun, was Sie wollen. Leider ist es ziemlich schwer, ein lazy-version dieser Funktion, ohne dass die oben genannten Leistungseinbußen (viele python gelieferten wie Kette.from_iterable sind nicht wirklich effizient, was ich nur gemerkt, nachdem umfangreiche Tests der drei verschiedenen Versionen von diesem code, bevor Sie sich auf dieser).Besser zu verstehen, was Los ist, unten ist ein Diagramm für diejenigen, die nicht mit
reduce
(Links), sonst bekannt als "Falten Links". Manchmal ist es gezeichnet mit einem ersten Wert an Stelle von k0 (nicht Teil der Liste, an die Funktion übergeben). HierJ
ist unserjoin
Funktion. Wir Vorverarbeiten jedes kn mitlift(k)
.Dies ist in der Tat das gleiche wie
functools.reduce
, aber wo unsere Funktion tut dies, um alle Schlüssel-Pfade des Baumes.Demonstration (was würde ich anders setzen, in docstring):
Leistung:
... seufz, glaube nicht, dass ist meine Schuld...
[unwichtig historische Anmerkung durch moderation-Themen]
Über die angebliche doppelte von Flatten ein Wörterbuch der Wörterbücher (2 Ebenen) von Listen in Python:
Diese Frage die Lösung implementiert werden kann, in Bezug auf diese eine Sequenz
sorted( sum(flatten(...),[]) )
. Der Umkehrschluss ist nicht möglich: zwar ist es wahr, dass die Werte vonflatten(...)
wiederhergestellt werden kann, von der angeblichen doppelten Zuordnung eines höher -, um-Akkumulator, kann man nicht wiederherstellen, die Tasten. (edit: Auch ist es stellt sich heraus, dass der angebliche doppelte owner ' s Frage völlig anders ist, dass Sie sich nur mit Wörterbüchern genau 2-Ebene tief, obwohl eine der Antworten auf dieser Seite erhalten Sie eine Allgemeine Lösung.)InformationsquelleAutor ninjagecko
Oder wenn Sie schon mit den pandas, die Sie tun können, es mit
json_normalize()
etwa so:Ausgabe:
Bisschen schade das es nicht verarbeitet werden 🙂
InformationsquelleAutor MYGz
Hier ist eine Art "funktionale", "one-liner" - Implementierung. Es ist rekursiv, und auf der Grundlage eines bedingten Ausdrucks und ein dict-comprehension.
Test:
InformationsquelleAutor dividebyzero
Code:
Ergebnisse:
Ich bin mit Python ist3.2, update für Ihre version von python.
lkey=''
in Ihrer Funktion definition statt, wenn Sie die Funktion aufrufen. Siehe andere Antworten in diesem Zusammenhang.InformationsquelleAutor Pavan Yalamanchili
Wenn Sie
pandas
es ist eine Funktion versteckt, die inpandas.io.json.normalize
genanntnested_to_record
welcher dies genau ist.InformationsquelleAutor Aaron N. Brock
Dies ist nicht nur Wörterbücher, sondern alle mapping-Typ implementiert .Elemente(). Weiter tritt schneller als es weicht mit einem geschickten Sprung eine if-Bedingung. Trotzdem credits gehen an Imran:
d
ist nicht eindict
aber ein benutzerdefinierter mapping-Typ, der nicht implementierenitems
, Ihre Funktion Versagen, genau dann und dort. Also, es funktioniert nicht für alle mapping-Typ, sondern nur diejenigen, die implementierenitems()
.haben Sie sich jemals begegnet eine mapping-Typ, der nicht implementieren
items
? Ich wäre neugierig, zu sehen.Ja, ich!!!!!!
Nein, Sie haben nicht per definition, wenn die Elemente nicht implementiert, es ist kein mapping-Typ.
Ja, ich!!!!!!
InformationsquelleAutor Davoud Taghawi-Nejad
Wie wäre es mit einem funktionale und performante Lösung in Python ist3.5?
Dies ist auch performant:
Im Einsatz:
Ich arbeitet seit Python 3.5. Wusste nicht, dass es nicht funktioniert mit 3.4. Du hast Recht das ist nicht sehr lesbar. Ich aktualisierte die Antwort. Hoffe es ist besser lesbar jetzt. 🙂
Hinzugefügt fehlt um den import. Hier noch die code schwer zu verstehen und ich denke, es ist ein gutes Beispiel, warum Guido van Rossum selbst entmutigt die Verwendung von lambda, reduzieren, filtern und anzeigen im Jahr 2005 bereits: artima.com/weblogs/viewpost.jsp?thread=98196
Ich bin damit einverstanden. Python ist nicht wirklich ausgelegt für funktionale Programmierung. Trotzdem finde ich
reduce
ist toll, wenn Sie benötigen, zu reduzieren Wörterbücher. Ich aktualisierte die Antwort. Sollte sich ein wenig mehr pythonic jetzt.InformationsquelleAutor Rotareti
Meine Python 3.3 Lösung mit Generatoren:
InformationsquelleAutor Atul
Einfache Funktion zum glätten verschachtelten dictionaries. Für Python 3 ersetzen
.iteritems()
mit.items()
Die Idee/Anforderung war:
Flachen Wörterbücher ohne halten der übergeordneten Schlüssel.
Beispiel der Nutzung:
Halten übergeordnete Schlüssel ist einfach wie gut.
InformationsquelleAutor Ivy Growing
Dies ist ähnlich zu beiden imran und ralu Antwort. Es nicht einen generator, sondern beschäftigt Rekursion mit einem Verschluss:
_flatten_dict
nie zurückgegeben, noch wird es voraussichtlich nie zurückgegeben werden. Kann es vielleicht bezeichnet werden als Unterfunktion oder eingeschlossen-Funktion statt.InformationsquelleAutor Jonathan Drake
Davoud ' s Lösung ist sehr schön, aber geben nicht zufriedenstellende Ergebnisse, wenn die nested dict enthält eine Liste von dicts, aber der code angepasst werden, für diesen Fall:
type([])
zu vermeiden, die einen Aufruf der Funktion für jedes Element desdict
.Bitte verwenden Sie
isinstance(v, list)
stattInformationsquelleAutor user3830731
Den Antworten auch wirklich funktionieren. Ich dachte, ich würde hinzufügen die unflatten-Funktion, die ich schrieb:
Hinweis: Das nicht-Konto-für " _ " ist bereits vorhanden in die Tasten, viel wie der flatten-Pendants.
InformationsquelleAutor tarequeh
Hier ist ein Algorithmus für die elegante, in-place-Ersatz. Getestet mit Python 2.7 und Python 3.5. Mit dem Punkt als Trennzeichen.
Beispiel:
Ausgabe:
Veröffentlichte ich diesen code hier zusammen mit dem passenden
unflatten_json
Funktion.InformationsquelleAutor Alexander Ryzhov
Wenn Sie möchten, Flachbild verschachtelte Wörterbuch und wollen alle einzigartige Tasten-Liste, dann ist hier die Lösung:
InformationsquelleAutor Ranvijay Sachan
Generatoren verwenden:
type(i).__name__=='dict'
ersetzt werden könnte, mittype(i) is dict
oder vielleicht sogar besserisinstance(d, dict)
(oderMapping
/MutableMapping
).InformationsquelleAutor Luka Rahne
Mithilfe von dict.popitem() in einfache verschachtelte-Liste-wie Rekursion:
InformationsquelleAutor FredAKA
InformationsquelleAutor Pari Rajaram
Ziehe ich immer Zugriff
dict
Objekte über.items()
, so zum glätten dicts ich benutzen den folgenden rekursiven generatorflat_items(d)
. Wenn Sie gernedict
wieder, einfach wickeln Sie es wie diese:flat = dict(flat_items(d))
InformationsquelleAutor Vladimir Ignatyev