Supposons que vous ayez ce dictionnaire
def loopDict(d): for k, v in d.iteritems(): if type(v) is dict: loopDict(v) else: print "{0} : {1}".format(k, v)
Et que vous vouliez que chaque dictionnaire imbriqué sur 3 (ou plus) soit aplati. Donc un résultat comme celui-ci.
{ "alpha": "one", "beta": { "beta1": "two", "beta2": "second two" }, "gamma": { "delta": { "delta1": "three", "delta2": "second three" }, "epsilon": { "zeta.zeta1": "four", "zeta.zeta2": "second four", "epsilon1": "five", "epsilon2": "second five" } } }
Comment y parvenir?
les balises et la structure du dictionnaire sont dynamiques (je veux refactoriser plusieurs dictionnaires avec des structures différentes mais une ligne dure à chaque troisième dictionnaire imbriqué)
Je sais que je peux parcourir chaque valeur, mais comment saurais-je quand j'ai atteint le troisième dictionnaire imbriqué?
{ "alpha": "one", "beta": { "beta1": "two", "beta2": "second two" }, "gamma": { "delta": { "delta1": "three", "delta2": "second three" }, "epsilon": { "zeta": { "zeta1": "four", "zeta2": "second four" }, "epsilon1": "five", "epsilon2": "second five" } } }
PS Je peux aplatir chaque dictionnaire à l'aide du module flatten_json
4 Réponses :
Je l'ai réparé!
Pour les personnes qui recherchent ça, j'ai fini par le réparer de cette façon.
xmldict = {yourdictionary}
for k, v in xmldict.items(): if isinstance(v, dict): for ke, va in v.items(): if isinstance(va, dict): for key, val in va.items(): if isinstance(val, dict): for key1, val1 in val.items(): if isinstance(val1, dict): xmldict[k][ke][key] = flatten(v)
Vous pouvez ajouter ou supprimer des boucles for en fonction de la profondeur (il existe probablement une fonction récursive plus soignée qui peut le faire pour vous)
J'ai corrigé ça, mais tu étais plus rapide! Cependant, je partage ma réponse, peut-être que cela peut être utile
d = { "alpha": "one", "beta": { "beta1": "two", "beta2": "second two" }, "gamma": { "delta": { "delta1": "three", "delta2": "second three" }, "epsilon": { "zeta": { "zeta1": "four", "zeta2": "second four" }, "epsilon1": "five", "epsilon2": "second five" } } } def flatten_dict(d): def items(): for key, value in d.items(): if isinstance(value, dict): for subkey, subvalue in flatten_dict(value).items(): yield key + "." + subkey, subvalue else: yield key, value return dict(items()) def loopDict(d, depth): for k, v in d.items(): if isinstance(v, dict): if depth > 0: d[k] = flatten_dict(v) if depth <= 0: loopDict(v, depth+1) return d d = loopDict(d, 0) print(d)
Vous pouvez utiliser la récursivité:
{ "alpha": "one", "beta": { "beta1": "two", "beta2": "second two" }, "gamma": { "delta": { "delta1": "three", "delta2": "second three" }, "epsilon": { "zeta.zeta1": "four", "zeta.zeta2": "second four", "epsilon1": "five", "epsilon2": "second five" } } }
import json print(json.dumps(walk(list(flatten(data))), indent=4))
Sortie:
data = {'alpha': 'one', 'beta': {'beta1': 'two', 'beta2': 'second two'}, 'gamma': {'delta': {'delta1': 'three', 'delta2': 'second three'}, 'epsilon': {'zeta': {'zeta1': 'four', 'zeta2': 'second four'}, 'epsilon1': 'five', 'epsilon2': 'second five'}}} def flatten(d, c = [], l = 1): for a, b in d.items(): if not isinstance(b, dict): yield a if l < 3 else '.'.join(c+[a]), b else: if l > 2: yield from flatten(b, c=c+[a] if l > 2 else c, l=l+1) else: yield (a, list(flatten(b, c=c+[a] if l > 2 else c, l=l+1))) def walk(d): return {a:b if not isinstance(b, list) else walk(b) for a, b in d}
L'approche la plus simple consiste à diviser celle-ci en deux étapes. Faites une boucle sur input_dictionary jusqu'à la profondeur cible souhaitée. Ensuite, appelez une fonction d'aplatissement sur les dictionnaires les plus internes:
{'alpha': 'one', 'beta': {'beta1': 'two', 'beta2': 'second two'}, 'gamma': {'delta': {'delta1': 'three', 'delta2': 'second three'}, 'epsilon': {'epsilon1': 'five', 'epsilon2': 'second five', 'zeta.zeta1': 'four', 'zeta.zeta2': 'second four'}}}
Ceci génère:
def flatten(d): for key, value in list(d.items()): if isinstance(value, dict): del d[key] for subkey, subvalue in value.items(): newkey = key + '.' + subkey d[newkey] = subvalue for v1 in input_dict.values(): if isinstance(v1, dict): for v2 in v1.values(): if isinstance(v2, dict): flatten(v2)
Si quelque chose de plus général est nécessaire, l'une ou les deux étapes peut être rendu récursif.
J'espère que cela vous aidera :-)
Pouvez-vous expliquer quel problème vous essayez de résoudre avec cela? En général, l'aplatissement d'une structure comme celle-ci n'améliorera pas la gestion des données.
ce sera moche de gérer les données comme vous le souhaitez
Vous pouvez ajouter un paramètre "level" / "depth" à votre fonction
loopDict
et l'augmenter à chaque récursivité, c'est pourquoi vous savez quand vous avez atteint le troisième niveau.