2012-04-17 17 views
5

Tengo una tabla de la forma:¿Traducir una tabla a un diccionario jerárquico?

A1, B1, C1, (value) 
A1, B1, C1, (value) 
A1, B1, C2, (value) 
A1, B2, C1, (value) 
A1, B2, C1, (value) 
A1, B2, C2, (value) 
A1, B2, C2, (value) 
A2, B1, C1, (value) 
A2, B1, C1, (value) 
A2, B1, C2, (value) 
A2, B1, C2, (value) 
A2, B2, C1, (value) 
A2, B2, C1, (value) 
A2, B2, C2, (value) 
A2, B2, C2, (value) 

me gustaría trabajar con él en Python como un diccionario, de la forma:

H = { 
    'A1':{ 
     'B1':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B2':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B3':{ 
      'C1':[],'C2':[],'C3':[] } 
    }, 
    'A2':{ 
     'B1':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B2':{ 
      'C1':[],'C2':[],'C3':[] }, 
     'B3':{ 
      'C1':[],'C2':[],'C3':[] } 
    } 
} 

Para que H[A][B][C] produce una única lista particular de valores. Para los diccionarios pequeños, podría definir la estructura de antemano como arriba, pero estoy buscando una forma eficiente de iterar sobre la tabla y construir un diccionario, sin especificar las claves del diccionario con anticipación.

+5

¿Siempre busca un triple de valores A, B, C? Si es así, sería mejor con un solo 'dict' usando esos triples como claves. –

Respuesta

8
input = [('A1', 'B1', 'C1', 'Value'), (...)] 

from collections import defaultdict 

tree = defaultdict(lambda: defaultdict(lambda: defaultdict(list))) 
#Alternatively you could use partial() rather than lambda: 
#tree = defaultdict(partial(defaultdict, partial(defaultdict, list))) 

for x, y, z, value in input: 
    tree[x][y][z].append(value) 
+1

Tenga en cuenta que si la tabla es un archivo de texto, querrá algo como '' con open ("tabla") como archivo: '' '' input = [line.split() para la línea en el archivo] ''. –

+2

Una alternativa para usar lambdas aquí es usar '' functools.partial() '': '' tree = defaultdict (partial (defaultdict, partial (defaultdict, list))) '- Esto me parece más claro, pero eso podría ser yo. –

+0

@Lattyware Interesante, gracias por eso. –

2
d = {} 
for (a, b, c, value) in your_table_of_tuples: 
    d.setdefault(a, {}).setdefault(b,{}).setdefault(c,[]).append(value) 
+0

¿Por qué usar '' setdefault() '' sobre un '' defaultdict''? –

+0

@Lattyware: ¿por qué no? – vartec

+0

Yo diría que es mucho más feo cuando lo usas. –

4

Si alguna vez único acceso H [A] [B] [C] (es decir, no H [A] oder H [A] [B] solo), me gustaría sugerir una Solución limpiadora IMO: utilice Tuples como índice predeterminado de errores:

from collections import defaultdict 
h = defaultdict(list) 
for a, b, c, value in input: 
    h[a, b, c].append(value) 
+0

Esta es una solución muy válida (y elegante) también, aunque sí requiere que no desee acceder a los subtítulos por separado. (editado para eliminar alguna sangría adicional, corchetes innecesarios y PEP-8ifying los nombres de las variables). –

+0

Gracias por publicar esta solución. En este caso, necesito acceder a los diccionarios secundarios, pero no especifiqué eso en la pregunta. Esto será extremadamente elegante si este caso existe en el futuro. –