Obtener matrices anidadas de un diccionario

Estoy tratando de analizar los resultados de una simulación para extraer todos los resultados que son matrices numpy. Al simular sobre un material simple, podríamos obtener un solo diccionario con valores de matriz:

{'material1':array, 'material2':array, ...} 

En simulaciones de materiales más complejos, terminamos con diccionarios nesteds como:

 {'material1': {'shellmaterial':array, 'corematerial':array}} 

La profundidad del anidamiento es arbitraria , y lo que quiero hacer es crear una gráfica donde todas las matrices disponibles se devuelvan al usuario, nombradas por su anidamiento. Así, por ejemplo, la estructura anterior terminaría como:

 {'material1.shellmaterial' : array, 'material1.corematerial' : array} 

Luego los pondríamos en un menú desplegable. para una fácil visualización en una ttwig. ¿Alguien tiene una buena manera de iterar en un diccionario nested arbitrariamente y devolver solo los valores de tipo de matriz con las nuevas claves como se muestra arriba?

Los resultados se deben almacenar de esta manera para la compatibilidad con json, por lo que no puedo volver atrás y refactorizar para evitar esto.

Esta es una función que utilicé con algunos árboles de decisión para el procesamiento del lenguaje, no es lo que desea, pero es la misma idea básica.

 def nodeMapForDict(d): node_map = [] node_path = [] def nodeRecursiveMap(d, node_path): for key, val in d.items(): if type(val) is not dict: node_map.append(node_path + [key]) if type(val) is dict: nodeRecursiveMap(val, node_path + [key]) nodeRecursiveMap(d, node_path) return node_map 

Y aquí hay uno que debe adaptarse a su caso de uso:

 def flattenDict(d): node_map = {} node_path = [] def nodeRecursiveMap(d, node_path): for key, val in d.items(): if type(val) is not dict: node_map['.'.join(node_path + [key])] = val if type(val) is dict: nodeRecursiveMap(val, node_path + [key]) nodeRecursiveMap(d, node_path) return node_map 

ejemplo:

 d= {'d': [1, 2, 3, 4], 'e': {'b': {'c': 1}}, 'a': {'b': 'c'}} In [49]: flattenDict(d) Out[49]: {'d': [1, 2, 3, 4], 'ebc': 1, 'a.b': 'c'} 

Para completar, aquí está la respuesta aceptada con un argumento de tipo que le permite filtrar los tipos de valores para retener. En mi caso, esto es solo valores de matriz, pero tal comportamiento es bastante útil para analizar los resultados de los archivos json o, en particular, los datos de nuestro progtwig de simulación.

 def flattenDict(d, *types): node_map = {} node_path = [] def nodeRecursiveMap(d, node_path): for key, val in d.items(): if type(val) in types: node_map['.'.join(node_path + [key])] = val if type(val) is dict: nodeRecursiveMap(val, node_path + [key]) nodeRecursiveMap(d, node_path) return node_map 

Por ejemplo, para retener solo los ints y las cadenas:

 d= {'d': [1, 2, 3, 4], 'e': {'b': {'c': 1}}, 'a': {'b': 'c'}} In [1]: flattenDict(d, int, basestring) Out[2]: {'ebc': 1, 'a.b': 'c'}