如何在Python中创建复杂的字典结构?

时间:2011-10-14 14:55:25

标签: python dictionary nested

我正在尝试从中读取数据并创建嵌套的字典字典。有一个类似的问题here,但我似乎无法弄清楚如何使解决方案适应我的特定问题。如果有人能够解决我的问题,我将非常感激。

基本上,我有一个看起来像这样的文件:

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 个答案:

答案 0 :(得分: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'。此外,这似乎包括字符串周围的单引号作为字符串的一部分,因此您可能需要清理它。

答案 1 :(得分: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 :(得分: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])

答案 3 :(得分: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始终相同,但未在您的问题中明确指定。

答案 4 :(得分: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

答案 5 :(得分:0)

使用设置默认值

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

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

print(result)