Как создать вложенный дикт в Python?
У меня есть 2 csv-файла. Первый-это файл данных, а второй-файл отображения. Файл отображения содержит 4 столбца Device_Name GDN Device_Type Device_OS
Это также столбцы, которые присутствуют в файле данных и должны быть обработаны.
Файл данных содержит данные с заполненным столбцом Device_Name и пустыми 3 столбцами rest. Файл сопоставления содержит все заполненные столбцы. Я хочу, чтобы мой код Python открыл оба файла и для каждого имени устройства в файле данных сопоставил его GDN, Device_Type и значение Device_OS из файла сопоставления.
Я знаю. как использовать dict, когда присутствуют только 2 столбца (1 необходимо сопоставить), но я не знаю, как это сделать, когда нужно сопоставить 3 столбца.
Ниже приведен код, с помощью которого я пытался выполнить отображение Device_Type
:
x = dict([])
with open("Pricing Mapping_2013-04-22.csv", "rb") as in_file1:
file_map = csv.reader(in_file1, delimiter=',')
for row in file_map:
typemap = [row[0],row[2]]
x.append(typemap)
with open("Pricing_Updated_Cleaned.csv", "rb") as in_file2, open("Data Scraper_GDN.csv", "wb") as out_file:
writer = csv.writer(out_file, delimiter=',')
for row in csv.reader(in_file2, delimiter=','):
try:
row[27] = x[row[11]]
except KeyError:
row[27] = ""
writer.writerow(row)
Возвращает значение Atribute Error
.
4 ответа:
Вложенный дикт - это словарь внутри словаря. Очень простая вещь.
>>> d = {} >>> d['dict1'] = {} >>> d['dict1']['innerkey'] = 'value' >>> d {'dict1': {'innerkey': 'value'}}
Вы также можете использовать
defaultdict
от самогоcollections
пакет для облегчения создания вложенных словарей.>>> import collections >>> d = collections.defaultdict(dict) >>> d['dict1']['innerkey'] = 'value' >>> d # currently a defaultdict type defaultdict(<type 'dict'>, {'dict1': {'innerkey': 'value'}}) >>> dict(d) # but is exactly like a normal dictionary. {'dict1': {'innerkey': 'value'}}
Вы можете заполнить это, как вы хотите.
Я бы рекомендовал в вашем коде что-то вроде следующего:
d = {} # can use defaultdict(dict) instead for row in file_map: # derive row key from something # when using defaultdict, we can skip the next step creating a dictionary on row_key d[row_key] = {} for idx, col in enumerate(row): d[row_key][idx] = col
Согласно вашему комментарию:
Может быть, выше код сбивает с толку вопрос. Мой проблема в двух словах: я есть 2 файлы.КШМ б.КШМ, а.КШМ имеет 4 колонки и Й К л, б.КШМ тоже есть этот столбец. i-это своего рода ключевые столбцы для этих CSV'. колонка j k l пусто в.CSV, но заполняется в б.КШМ. Я хочу сопоставить значения j k л столбцов, используя " Я " как ключевой столбец из B.CSV в.файл CSV
Мое предложение было бы чем-то вроде этого (без использования defaultdict):
a_file = "path/to/a.csv" b_file = "path/to/b.csv" # read from file a.csv with open(a_file) as f: # skip headers f.next() # get first colum as keys keys = (line.split(',')[0] for line in f) # create empty dictionary: d = {} # read from file b.csv with open(b_file) as f: # gather headers except first key header headers = f.next().split(',')[1:] # iterate lines for line in f: # gather the colums cols = line.strip().split(',') # check to make sure this key should be mapped. if cols[0] not in keys: continue # add key to dict d[cols[0]] = dict( # inner keys are the header names, values are columns (headers[idx], v) for idx, v in enumerate(cols[1:]))
Обратите внимание, что для разбора csv-файлов существует csv модуль .
UPDATE : для произвольной длины вложенного словаря перейдите к этому ответу.
Используйте функцию defaultdict из коллекций.
Высокая производительность: "если ключ не в dict" очень дорого, когда набор данных большой.
Низкое обслуживание: сделайте код более читаемым и легко расширяемым.
from collections import defaultdict target_dict = defaultdict(dict) target_dict[key1][key2] = val
Для произвольных уровней вложенности:
In [2]: def nested_dict(): ...: return collections.defaultdict(nested_dict) ...: In [3]: a = nested_dict() In [4]: a Out[4]: defaultdict(<function __main__.nested_dict>, {}) In [5]: a['a']['b']['c'] = 1 In [6]: a Out[6]: defaultdict(<function __main__.nested_dict>, {'a': defaultdict(<function __main__.nested_dict>, {'b': defaultdict(<function __main__.nested_dict>, {'c': 1})})})
Важно помнить, что при использовании defaultdict и подобных вложенных модулей dict, таких как nested_dict, поиск несуществующего ключа может непреднамеренно создать новую запись ключа в dict и вызвать большой хаос. Вот пример Python3 с nested_dict.
import nested_dict as nd nest = nd.nested_dict() nest['outer1']['inner1'] = 'v11' nest['outer1']['inner2'] = 'v12' print('original nested dict: \n', nest) try: nest['outer1']['wrong_key1'] except KeyError as e: print('exception missing key', e) print('nested dict after lookup with missing key. no exception raised:\n', nest) # instead convert back to normal dict nest_d = nest.to_dict(nest) try: print('converted to normal dict. Trying to lookup Wrong_key2') nest_d['outer1']['wrong_key2'] except KeyError as e: print('exception missing key', e) else: print(' no exception raised:\n') # or use dict.keys to check if key in nested dict. print('checking with dict.keys') print(list(nest['outer1'].keys())) if 'wrong_key3' in list(nest.keys()): print('found wrong_key3') else: print(' did not find wrong_key3')
Вывод:
original nested dict: {"outer1": {"inner2": "v12", "inner1": "v11"}} nested dict after lookup with missing key. no exception raised: {"outer1": {"wrong_key1": {}, "inner2": "v12", "inner1": "v11"}} converted to normal dict. Trying to lookup Wrong_key2 exception missing key 'wrong_key2' checking with dict.keys ['wrong_key1', 'inner2', 'inner1'] did not find wrong_key3