Diccionario arbitrariamente anidado de tuplas
Dado un diccionario con tuplas como claves (y números / escalares como valores), ¿cuál es una forma pitónica de convertir a un diccionario anidado? El problema es que de entrada a entrada, las tuplas son de longitud arbitraria.
Abajo,d1
, d2
yd3
demuestre una mayor anidación:
from itertools import product
d1 = dict(zip(product('AB', [0, 1]), range(2*2)))
d2 = dict(zip(product('AB', [0, 1], [True, False]), range(2*2*2)))
d3 = dict(zip(product('CD', [0, 1], [True, False], 'AB'), range(2*2*2*2)))
Y sus versiones anidadas resultantes serían:
# For d1
{'A': {0: 0, 1: 1}, 'B': {0: 2, 1: 3}}
# For d2
{'A': {0: {True: 0, False: 1}, 1: {True: 2, False: 3}},
'B': {0: {True: 4, False: 5}, 1: {True: 6, False: 7}}}
# Beginning of result for d3
{
'C': {
0: {
True: {
'A': 0
'B': 1
},
False: {
'A': 2,
'B': 3
},
1: # ...
Mis intentos: me gusta este truco para inicializar una estructura de datos vacía, que se proporciona en varias otras respuestas SO:
from collections import defaultdict
def nested_dict():
return defaultdict(nested_dict)
Pero tengo problemas para implementar esto porque la cantidad de niveles es incierta. Podría usar algo como:
def nest(d: dict) -> dict:
res = nested_dict()
for (i, j, k), v in d.items():
res[i][j][k] = v
return res
Pero esto seríasolament trabajar parad2
porque sus teclas tienen 3 niveles (i, j, k) arriba.
Este es mi intento de encontrar una solución para generalizar esto, pero supongo que hay una ruta más simple.
def set_arbitrary_nest(keys, value):
"""
>>> keys = 1, 2, 3
>>> value = 5
result --> {1: {2: {3: 5}}}
"""
it = iter(keys)
last = next(it)
res = {last: {}}
lvl = res
while True:
try:
k = next(it)
lvl = lvl[last]
lvl[k] = {}
last = k
except StopIteration:
lvl[k] = value
return res
>>> set_arbitrary_nest([1, 2, 3], 5)
{1: {2: {3: 5}}}