2011-12-12 7 views
5

estoy tratando con una estructura JSON, que se emite a mí en las estructuras de la siguiente manera:aplanamiento una lista de dicts de listas de dicts (etc) de profundidad desconocida en Python (estructura JSON pesadilla)

[{u'item': u'something', 
    u'data': { 
      u'other': u'', 
      u'else': 
       [ 
        { 
        u'more': u'even more', 
        u'argh': 
         { 
          ...etc..etc 

Como puede ver, estos son dictados y listas anidados. Se ha debatido mucho sobre el aplazamiento recursivo, pero todavía no he encontrado uno que pueda tratar una lista de diccionarios que a su vez puede contener diccionarios de listas, listas de listas, diccionarios de diccionarios, etc. que son de profundidad desconocida! En algunos casos, la profundidad puede ser de hasta 100 o más. He estado tratando de esto hasta ahora sin mucha suerte (Python 2.7.2):

def flatten(structure): 
    out = [] 
    for item in structure: 
     if isinstance(item, (list, tuple)): 
      out.extend(flatten(item)) 
     if isinstance(item, (dict)): 
      for dictkey in item.keys(): 
       out.extend(flatten(item[dictkey])) 
     else: 
      out.append(item) 
    return out 

¿Alguna idea?

ACTUALIZACIÓN Esto más o menos obras:

def flatten(l): 
    out = [] 
    if isinstance(l, (list, tuple)): 
     for item in l: 
      out.extend(flatten(item)) 
    elif isinstance(l, (dict)): 
     for dictkey in l.keys(): 
      out.extend(flatten(l[dictkey])) 
    elif isinstance(l, (str, int, unicode)): 
     out.append(l) 
    return out 
+0

Sería de gran ayuda si nos pudiera suministrar un ejemplo de la clase de salida desea (con un ejemplo muy simple - tal vez sólo una o dos Dicts/listas de profundidad) –

+0

Una simple lista al igual que [ item0, item1, item2 ...] es lo que yo apuntaría – LittleBobbyTables

Respuesta

9

Dado que la profundidad de sus datos es arbitraria, es más fácil que recurrir a la recursividad para aplanarlo. Esta función crea un diccionario plano, con la ruta de cada elemento de datos compuesto como la clave, para evitar colisiones.

Puede recuperar su contenido más tarde con for key in sorted(dic_.keys()), por ejemplo.

No lo probé, ya que no proporcionó un fragmento "válido" de sus datos.

def flatten(structure, key="", path="", flattened=None): 
    if flattened is None: 
     flattened = {} 
    if type(structure) not in(dict, list): 
     flattened[((path + "_") if path else "") + key] = structure 
    elif isinstance(structure, list): 
     for i, item in enumerate(structure): 
      flatten(item, "%d" % i, path + "_" + key, flattened) 
    else: 
     for new_key, value in structure.items(): 
      flatten(value, new_key, path + "_" + key, flattened) 
    return flattened 
+0

Trate de reemplazar la "ruta +" _ "+ tecla" por "_". join (filter (None, [path, key])). Esto asegurará que no se impriman caracteres de subrayado feos en caso de que la ruta o la clave estén en blanco. –

Cuestiones relacionadas