Cuente las hojas finales no vacías de una estructura de datos de matriz / disco de python: ¿algoritmo recursivo?

Estoy buscando una función para encontrar todos los puntos finales no vacíos de un tipo de estructura compleja de diccionario / matriz. Creo que debido a que no conozco la cantidad de arreglos nesteds o sus ubicaciones, tendría que ser recursivo, y aún no entiendo completamente esa forma de pensar.

Así que para el dictado nested:

x = {"top": {"middle" : [ {"nested": "value"}, {"nested":"val2"}, {"nested":""} ], "last" : [ {"nested": [ {"first":1,"second":1}, {"first":0,"second":""} ] }, {"nested": [ {"first":1,"second":1}, {"first":1,"second":2} ] }, {"nested": [ {"first":1,"second":1}, {"first":"","second":""} ] } ] }, "other":1} 

y la variable “rutas” nombrada de la siguiente manera, donde “.XX” designa que hay una matriz (en el estilo de variety.js):

 vars = ["top.middle.XX.nested", "top.last.XX.nested.XX.first", "top.last.XX.nested.XX.second", "other"] 

Me gustaría una función f(x,y) que pueda devolver …

 f(x,"top.middle.XX.nested") = 2/3 f(x,"top.last.XX.nested.XX.first") = 5/6 f(x,"top.last.XX.nested.XX.second") = 4/6 f(x,"other") = 1 

El problema para mí parece ser tratar de construir el árbol a medida que avanza y dónde colocar el contador para nulos. Por lo tanto, no entiendo bien cómo registrar los contadores o hacer la recursión correctamente.

Tal vez esto puede guiarlo en la dirección correcta. byPath recostack los elementos del diccionario nesteds. Una vez llamado, básicamente puede aplanar la lista resultante y verificar si se cumple su condición (como elem != '' O not elem o lo que sea):

 x = #your x as posted def byPath (tree, path): try: head, tail = path.split ('.', 1) except: return tree [path] if head == 'XX': return [byPath (node, tail) for node in tree] else: return byPath (tree [head], tail) print (byPath (x, 'top.middle.XX.nested') ) print (byPath (x, 'top.last.XX.nested.XX.first') ) print (byPath (x, 'top.last.XX.nested.XX.second') ) print (byPath (x, 'other') ) 

EDITAR : Aquí está la parte para contar realmente aquellos elementos que no son una cadena vacía:

 def count (result): if isinstance (result, list): total = 0 positive = 0 for e in result: r = count (e) total += r [1] positive += r [0] return (positive, total) else: return (0 if result == '' else 1, 1) a = byPath (x, 'top.middle.XX.nested') b = byPath (x, 'top.last.XX.nested.XX.first') c = byPath (x, 'top.last.XX.nested.XX.second') d = byPath (x, 'other') for x in [a, b, c, d]: print (count (x) ) 

Poniendo todo junto:

 def f (tree, path): return count (byPath (tree, path) ) for path in ['top.middle.XX.nested', 'top.last.XX.nested.XX.first', 'top.last.XX.nested.XX.second', 'other']: print (path, f (x, path) )