Ich habe eine komplexe Wörterbuchstruktur, auf die ich über eine Liste von Schlüsseln zugreifen möchte, um das richtige Element zu adressieren.
dataDict = {
"a":{
"r": 1,
"s": 2,
"t": 3
},
"b":{
"u": 1,
"v": {
"x": 1,
"y": 2,
"z": 3
},
"w": 3
}
}
maplist = ["a", "r"]
oder
maplist = ["b", "v", "y"]
Ich habe den folgenden Code erstellt, der funktioniert, aber ich bin sicher, dass es einen besseren und effizienteren Weg gibt, dies zu tun, wenn jemand eine Idee hat.
# Get a given data from a dictionary with position provided as a list
def getFromDict(dataDict, mapList):
for k in mapList: dataDict = dataDict[k]
return dataDict
# Set a given data in a dictionary with position provided as a list
def setInDict(dataDict, mapList, value):
for k in mapList[:-1]: dataDict = dataDict[k]
dataDict[mapList[-1]] = value
python
list
dictionary
Kolergie
quelle
quelle
Antworten:
Verwenden Sie
reduce()
diese Option, um das Wörterbuch zu durchlaufen:und wiederverwenden
getFromDict
, um den Speicherort für den Wert zu finden fürsetInDict()
:Alle bis auf das letzte Element in
mapList
werden benötigt, um das 'übergeordnete' Wörterbuch zu finden, zu dem der Wert hinzugefügt werden soll. Verwenden Sie dann das letzte Element, um den Wert auf den richtigen Schlüssel zu setzen.Demo:
Beachten Sie, dass der Python PEP8- Styleguide snake_case-Namen für Funktionen vorschreibt . Das Obige funktioniert genauso gut für Listen oder eine Mischung aus Wörterbüchern und Listen, daher sollten die Namen wirklich sein
get_by_path()
undset_by_path()
:quelle
try:
,except (KeyError, IndexError): return default_value
um die aktuellereturn
Zeile.dict.get()
Änderungen wird die Semantik geändert, da dies bei fehlenden NamenNone
eher zurückkehrt als erhöhtKeyError
. Alle nachfolgenden Namen lösen dann eine ausAttributeError
.operator
ist eine Standardbibliothek, die hier nicht vermieden werden muss.from functools import reduce
.for
Schleife zu verwenden. Siehe das Zitat aus den Neuerungen in Python 3.0 .KeyError
) - eine Lösung finden Sie in der Antwort von @ eafitWarum also nicht die vorgeschlagene Methode aus Kolergys Frage verwenden, um einen Wert zu erhalten:
Und der Code aus der Antwort von @ eafit zum Festlegen eines Werts:
Beide arbeiten direkt in Python 2 und 3
quelle
getFromDict
sind, kann dies den Anrufer zerstörendataDict
. Ich würdecopy.deepcopy(dataDict)
zuerst. Natürlich ist (wie geschrieben) dieses Verhalten in der zweiten Funktion erwünscht.Die Verwendung von "Reduzieren" ist clever, aber die Set-Methode des OP kann Probleme haben, wenn die übergeordneten Schlüssel nicht im verschachtelten Wörterbuch vorhanden sind. Da dies der erste SO-Beitrag ist, den ich in meiner Google-Suche für dieses Thema gesehen habe, möchte ich ihn etwas verbessern.
Die set-Methode in ( Festlegen eines Werts in einem verschachtelten Python-Wörterbuch anhand einer Liste von Indizes und Werten ) scheint gegenüber fehlenden Elternschlüsseln robuster zu sein. So kopieren Sie es:
Es kann auch praktisch sein, eine Methode zu haben, die den Schlüsselbaum durchläuft und alle absoluten Schlüsselpfade abruft, für die ich Folgendes erstellt habe:
Eine Verwendung davon besteht darin, den verschachtelten Baum unter Verwendung des folgenden Codes in einen Pandas-DataFrame zu konvertieren (vorausgesetzt, alle Blätter im verschachtelten Wörterbuch haben dieselbe Tiefe).
quelle
nested_set
?Diese Bibliothek kann hilfreich sein: https://github.com/akesterson/dpath-python
quelle
Wie wäre es mit rekursiven Funktionen?
So erhalten Sie einen Wert:
Und um einen Wert festzulegen:
quelle
Reiner Python-Stil ohne Import:
Ausgabe
quelle
Eine alternative Möglichkeit, wenn Sie keine Fehler auslösen möchten, wenn einer der Schlüssel fehlt (damit Ihr Hauptcode ohne Unterbrechung ausgeführt werden kann):
In diesem Fall wird None zurückgegeben, wenn einer der Eingabetasten nicht vorhanden ist. Dies kann als Überprüfung Ihres Hauptcodes verwendet werden, um eine alternative Aufgabe auszuführen.
quelle
Anstatt jedes Mal einen Leistungstreffer zu erzielen, wenn Sie einen Wert nachschlagen möchten, können Sie das Wörterbuch einmal reduzieren und dann einfach den Schlüssel wie nachschlagen
b:v:y
Auf diese Weise können Sie einfach nach Artikeln suchen, mit
flat_dict['b:v:y']
denen Sie diese erhalten1
.Und anstatt das Wörterbuch bei jeder Suche zu durchlaufen, können Sie dies möglicherweise beschleunigen, indem Sie das Wörterbuch reduzieren und die Ausgabe speichern, sodass eine Suche nach Kaltstart das Laden des reduzierten Wörterbuchs und das einfache Durchführen einer Schlüssel- / Wertsuche mit Nein bedeutet Durchquerung.
quelle
Dieses Problem wurde durch Rekursion gelöst:
Anhand Ihres Beispiels:
quelle
Wie wäre es, wenn Sie das Element dict überprüfen und dann festlegen, ohne alle Indizes zweimal zu verarbeiten?
Lösung:
Beispielworkflow:
Prüfung
quelle
Sehr spät zur Party, aber das Posten für den Fall, dass dies jemandem in der Zukunft helfen könnte. Für meinen Anwendungsfall hat die folgende Funktion am besten funktioniert. Funktioniert, um einen beliebigen Datentyp aus dem Wörterbuch zu ziehen
dict ist das Wörterbuch, das unseren Wert enthält
Liste ist eine Liste von "Schritten" in Richtung unseres Wertes
quelle
Es ist erfreulich, diese Antworten zu sehen, wenn zwei statische Methoden zum Festlegen und Abrufen verschachtelter Attribute vorhanden sind. Diese Lösungen sind weitaus besser als die Verwendung verschachtelter Bäume https://gist.github.com/hrldcpr/2012250
Hier ist meine Implementierung.
Verwendung :
Aufruf eines verschachtelten Attributs festlegen
sattr(my_dict, 1, 2, 3, 5) is equal to my_dict[1][2][3][4]=5
Um einen verschachtelten Attributaufruf zu erhalten
gattr(my_dict, 1, 2)
quelle
Ich empfehle Ihnen,
python-benedict
über den Schlüsselpfad auf verschachtelte Elemente zuzugreifen.Installieren Sie es mit
pip
:Dann:
Hier die vollständige Dokumentation: https://github.com/fabiocaccamo/python-benedict
quelle
Wenn Sie auch die Möglichkeit haben möchten, mit beliebigem JSON einschließlich verschachtelter Listen und Diktate zu arbeiten und ungültige Suchpfade gut zu handhaben, ist hier meine Lösung:
quelle
eine Methode zum Verketten von Zeichenfolgen:
quelle
Diese funktionalen Setter und Mapper erweitern @DomTomCat und den Ansatz anderer und funktionieren für verschachtelte
dict
und (dh modifizierte Daten über Deepcopy zurückgeben, ohne die Eingabe zu beeinflussen)list
.Setter:
Mapper:
quelle
Sie können die
eval
Funktion in Python verwenden.Erläuterung
Für Ihre Beispielabfrage:
maplist = ["b", "v", "y"]
nestq
wird sein,"nest['b']['v']['y']"
wonest
ist das verschachtelte Wörterbuch.Die
eval
eingebaute Funktion führt die angegebene Zeichenfolge aus. Es ist jedoch wichtig, vorsichtig mit möglichen Schwachstellen umzugehen, die sich aus der Verwendung voneval
Funktionen ergeben. Die Diskussion finden Sie hier:In der
nested_parse()
Funktion habe ich sichergestellt, dass keine__builtins__
Globals verfügbar sind und nur die verfügbare lokale Variable dasnest
Wörterbuch ist.quelle
Sie können pydash verwenden:
https://pydash.readthedocs.io/en/latest/api.html
quelle