2011-10-14 71 views
0

我正在嘗試讀取數據並創建一個字典的嵌套字典。有一個類似的問題here,但我似乎無法弄清楚如何使解決方案適應我的特定問題。如果有人能爲我的問題解釋我的解決方案,我將非常感激。如何在Python中創建複雜的字典結構?

基本上,我有一個看起來像這樣的文件:

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 

我需要創建一個複雜的字典,看起來像這樣:

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

我可以創建內部字典,但我無法弄清楚如何創建外部字典。這是我的內部字典代碼:

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 

有人可以解釋如何創建外部字典嗎?我唯一的想法是讀取文件並創建內部字典,然後重新讀取該文件以創建外部字典。當然必須有一個更簡單的方法?先謝謝您的幫助!

回答

6

這是你想要完成的嗎?

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) 

請注意,在您的示例中,'value2'在'value1'的位置。此外,這似乎包括字符串周圍的單引號作爲字符串的一部分,因此您可能需要清理它。

+0

太棒了!感謝您的幫助,這使我的一天! – drbunsen

0

如果你讀的叫s爲了簡潔變量文件,以下可能的工作:

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]) 

假設string始終是每character是相同的,但並沒有明確地在你的問題中指定。

0

下面是我該怎麼做。比你的短得多。這種方式只保留內存中所有數據的一個副本,只能從文件中一次讀取一行。

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

考慮:

$ 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 

此:

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   

產地:

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

使用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])