Aplanar diccionarios anidados, comprimir claves

Resuelto A Timmes asked hace 13 años • 0 respuestas

Supongamos que tiene un diccionario como:

{'a': 1,
 'c': {'a': 2,
       'b': {'x': 5,
             'y' : 10}},
 'd': [1, 2, 3]}

¿Cómo harías para aplanar eso en algo como:

{'a': 1,
 'c_a': 2,
 'c_b_x': 5,
 'c_b_y': 10,
 'd': [1, 2, 3]}
A Timmes avatar May 17 '11 14:05 A Timmes
Aceptado

Básicamente, de la misma manera que aplanarías una lista anidada, solo tienes que hacer el trabajo adicional para iterar el dict por clave/valor, crear nuevas claves para tu nuevo diccionario y crear el diccionario en el paso final.

from collections.abc import MutableMapping

def flatten(dictionary, parent_key='', separator='_'):
    items = []
    for key, value in dictionary.items():
        new_key = parent_key + separator + key if parent_key else key
        if isinstance(value, MutableMapping):
            items.extend(flatten(value, new_key, separator=separator).items())
        else:
            items.append((new_key, value))
    return dict(items)

>>> flatten({'a': 1, 'c': {'a': 2, 'b': {'x': 5, 'y' : 10}}, 'd': [1, 2, 3]})
{'a': 1, 'c_a': 2, 'c_b_x': 5, 'd': [1, 2, 3], 'c_b_y': 10}
Imran avatar May 17 '2011 07:05 Imran

O si ya estás usando pandas, puedes hacerlo json_normalize()así:

import pandas as pd

d = {'a': 1,
     'c': {'a': 2, 'b': {'x': 5, 'y' : 10}},
     'd': [1, 2, 3]}

df = pd.json_normalize(d, sep='_')

print(df.to_dict(orient='records')[0])

Producción:

{'a': 1, 'c_a': 2, 'c_b_x': 5, 'c_b_y': 10, 'd': [1, 2, 3]}
Mohammad Yusuf avatar Jan 23 '2017 08:01 Mohammad Yusuf