2011-10-14 45 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])