Как создать сложную структуру словаря в Python? - PullRequest
0 голосов
/ 14 октября 2011

Я пытаюсь прочитать данные из и создать вложенный словарь словарей.Здесь есть похожий вопрос , но я не могу понять, как адаптировать решение к моей конкретной проблеме.Я был бы очень признателен, если бы кто-то мог объяснить мне решение моей проблемы.

По сути, у меня есть файл, который выглядит следующим образом:

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

Может кто-нибудь объяснить, как создать внешний словарь?Единственная идея, которая у меня есть, - это прочитать файл и создать внутренний словарь, а затем перечитать файл, чтобы создать внешний словарь.Наверняка должен быть более простой способ?Заранее спасибо за помощь!

Ответы [ 5 ]

6 голосов
/ 14 октября 2011

Это то, чего вы хотите достичь?

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'.Кроме того, это, по-видимому, включает в себя одинарные кавычки вокруг строк как часть строки, поэтому вам может потребоваться очистить это.

2 голосов
/ 14 октября 2011

Использовать 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])
2 голосов
/ 14 октября 2011

Дано:

$ 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]]}}
0 голосов
/ 14 октября 2011

Вот как бы я это сделал. Не намного короче твоего. Таким образом, в памяти сохраняется только одна копия всех данных, и только чтение одной строки за раз из файла.

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
0 голосов
/ 14 октября 2011

Если вы читаете файл в переменной с именем 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, но это не былоt явно указано в вашем вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...