Ich fand diese Frage / Antwort sehr interessant, da sie verschiedene Lösungen für dasselbe Problem bietet. Ich habe all diese Funktionen übernommen und sie mit einem komplexen Wörterbuchobjekt getestet. Ich musste zwei Funktionen aus dem Test herausnehmen, weil sie zu viele Fehlschläge hatten und keine Rückgabe von Listen oder Diktaten als Werte unterstützten, was ich für wesentlich halte, da eine Funktion für fast alle kommenden Daten vorbereitet werden sollte .
Also habe ich die anderen Funktionen in 100.000 Iterationen durch das timeit
Modul gepumpt und die Ausgabe kam zu folgendem Ergebnis:
0.11 usec/pass on gen_dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
6.03 usec/pass on find_all_items(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.15 usec/pass on findkeys(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1.79 usec/pass on get_recursively(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.14 usec/pass on find(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
0.36 usec/pass on dict_extract(k,o)
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Alle Funktionen hatten dieselbe Nadel zum Suchen ('Protokollierung') und dasselbe Wörterbuchobjekt, das wie folgt aufgebaut ist:
o = { 'temparature': '50',
'logging': {
'handlers': {
'console': {
'formatter': 'simple',
'class': 'logging.StreamHandler',
'stream': 'ext://sys.stdout',
'level': 'DEBUG'
}
},
'loggers': {
'simpleExample': {
'handlers': ['console'],
'propagate': 'no',
'level': 'INFO'
},
'root': {
'handlers': ['console'],
'level': 'DEBUG'
}
},
'version': '1',
'formatters': {
'simple': {
'datefmt': "'%Y-%m-%d %H:%M:%S'",
'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
}
}
},
'treatment': {'second': 5, 'last': 4, 'first': 4},
'treatment_plan': [[4, 5, 4], [4, 5, 4], [5, 5, 5]]
}
Alle Funktionen lieferten das gleiche Ergebnis, aber die Zeitunterschiede sind dramatisch! Die Funktion gen_dict_extract(k,o)
ist meine Funktion, die von den Funktionen hier angepasst wurde. Eigentlich ist sie der find
Funktion von Alfe ziemlich ähnlich , mit dem Hauptunterschied, dass ich überprüfe, ob das angegebene Objekt eine Iteritems-Funktion hat, falls während der Rekursion Zeichenfolgen übergeben werden:
def gen_dict_extract(key, var):
if hasattr(var,'iteritems'):
for k, v in var.iteritems():
if k == key:
yield v
if isinstance(v, dict):
for result in gen_dict_extract(key, v):
yield result
elif isinstance(v, list):
for d in v:
for result in gen_dict_extract(key, d):
yield result
Diese Variante ist also die schnellste und sicherste der Funktionen hier. Und find_all_items
ist unglaublich langsam und weit weg von der zweitlangsamsten, get_recursivley
während der Rest, außer dict_extract
, nahe beieinander liegt. Die Funktionen fun
und funktionieren keyHole
nur, wenn Sie nach Zeichenfolgen suchen.
Interessanter Lernaspekt hier :)