2011-10-14 9 views
0

J'essaie de lire dans les données et de créer un dictionnaire imbriqué de dictionnaires. Il y a une question similaire here, mais je n'arrive pas à comprendre comment adapter une solution à mon problème particulier. Je serais très reconnaissant si quelqu'un pourrait m'expliquer une solution pour mon problème.Comment créer une structure de dictionnaire complexe en Python?

Fondamentalement, j'ai un fichier qui ressemble à ceci:

A 'abc' 12 0.001 
B 'tex' 34 0.002 
B 'tex' 78 0.005 
E 'yet' 88 0.090 
A 'abc' 22 0.120 

Je dois créer un dictionnaire complexe qui ressemble à ceci:

complete_dict = {A:{'abc':[[12, 0.001], [22, 0.120]]}, 
       B:{'tex':[[34, 0.002], [78, 0.005]]}, 
       E:{'yet':[[88, 0.090]]}} 

je peux créer le dictionnaire intérieur, mais je ne peut pas comprendre comment créer le dictionnaire externe. Voici mon code pour le dictionnaire interne:

with open('data.txt', mode="r") as data_file: 
    fieldnames = ('character', 'string', 'value1', 'value2') 
    reader = csv.DictReader(data_file, fieldnames=fieldnames, delimiter="\t") 
    inner_dict = {} 
    for row in reader: 
     values = [int(row['value1']), float(row['value2'])] 
     string = row['string'] 
     if string in inner_dict: 
      inner_dict[string].append(values) 
     else: 
      inner_dict[string] = values 

Quelqu'un pourrait-il expliquer comment créer le dictionnaire externe? La seule idée que j'ai est de lire le fichier et de créer le dictionnaire interne, puis relire le fichier pour créer le dictionnaire externe. Sûrement il doit y avoir un moyen plus facile? Merci d'avance pour l'aide!

Répondre

6

Est-ce ce que vous cherchez à accomplir?

with open('data.txt', mode="r") as data_file: 
    fieldnames = ('character', 'string', 'value1', 'value2') 
    reader = csv.DictReader(data_file, fieldnames=fieldnames, delimiter="\t") 

    complete_dict = {} 
    for row in reader: 
     char_dict = complete_dict.setdefault(row['character'], {}) 
     values_list = char_dict.setdefault(row['string'], []) 
     values = [int(row['value1']), float(row['value2'])] 
     values_list.append(values) 

pprint.pprint(complete_dict) 

Notez que dans votre exemple vous avez 'value2' où vous voulez 'value1'. En outre, cela semble inclure les guillemets simples autour des chaînes dans le cadre de la chaîne, de sorte que vous devrez peut-être nettoyer cela.

+0

Fantastique! Merci pour l'aide, cela a fait ma journée! – drbunsen

0

Si vous lisez le fichier dans une variable appelée s par souci de concision, ce qui suit pourrait fonctionner:

d = {} 
for l in s.split('\n'): 
    character, string, val1, val2 = l.split('\t') 
    if not d.has_key(character): 
     d[character] = { string: [] } 
    d[character][string].append([val1, val2]) 

est toujours Supposant string la même chose pour tous les character, mais qui n'a pas été explicitement spécifié dans votre question.

0

Voici comment je le ferais. Pas beaucoup plus court que le tien. De cette façon, seule une copie de toutes les données est conservée en mémoire, ne lisant qu'une ligne à la fois à partir du fichier.

f = open('data.txt', 'r') 
rows = imap(lambda line: line.split('\t'), f) 
result = {} 
for key1, key2, val1, val2 in rows: 
    key2 = eval(key2) # safe only if you know the value is a quoted string 
    if key1 not in result: 
    result[key1] = {} 
    if key2 not in result[key1]: 
    result[key1][key2] = [] 
    result[key1][key2].append([int(val1), float(val2)]) 
f.close() # prevent lingering open file 
2

Vu:

$ cat data.txt 
A 'abc' 12 0.001 
B 'tex' 34 0.002 
B 'tex' 78 0.005 
E 'yet' 88 0.090 
A 'abc' 22 0.120 

Ce:

import csv 

d={} 
with open('data.txt', mode="r") as data_file: 
    fieldnames = ('character', 'string', 'value1', 'value2') 
    reader = csv.DictReader(data_file, fieldnames=fieldnames, delimiter="\t") 
    for row in reader: 
     c=row['character'] 
     values = [int(row['value1']), float(row['value2'])] 
     s = row['string'] 
     if c not in d: d[c]={} 
     if s not in d[c]: d[c][s] = [] 
     d[c][s].append(values) 

print d   

Produit:

{'A': {"'abc'": [[12, 0.001], [22, 0.12]]}, 
'B': {"'tex'": [[34, 0.002], [78, 0.005]]}, 
'E': {"'yet'": [[88, 0.09]]}} 
2

Utilisez un defaultdict.

from collections import defaultdict 
complete_dict = defaultdict(lambda: defaultdict(list)) 

with open('data.txt', mode="rb") as data_file: 
    reader = csv.reader(data_file, delimiter="\t") 
    for c, s, v1, v in reader: 
     complete_dict[c][s].append([v1, v2]) 
Questions connexes