#python #list #dictionary #nested
Вопрос:
Это может быть очень простым вопросом для большинства, но испытывающий трудности студент был бы признателен за некоторую помощь. У меня есть словарь со списком вложенных словарей. Некоторые элементы отсутствуют или расположены в неправильном порядке.
Я пытаюсь экспортировать его в csv в определенном порядке (список) Мне нужно сравнить, есть ли элементы в списке с именами ключей, и вернуть значения. Если ключ не существует, чтобы вернуть «N/A»
Образец
my_list=["_id", "count", "f_name", "l_name", "number", "country]
my_dict = [{
"_id": 123,
"count": 345,
"account": [
{
"f_name": "Adam",
"l_name": "Adamson",
"number": 1,
"country": "Argentina"
},
{,
"l_name": "Charlson",
"country": "Canada"
},
{
"f_name": "David",
"country": "Denmark",
"number": 3,
"l_name": "Davidson"
},
]
},
{
"_id": 678,
"count": 981,
"account": [
{
"f_name": "Edvin",
"number": 4,
"country": "Equador"
},
]
}]
Ожидаемый Результат
_id | count | f_name | l_name | number | country
------------------------------------------------------
123 | 345 | Adam | Adamson | 1 | Argentina
------------------------------------------------------
123 | 345 | N/A | Charlosn | N/A | Canada
------------------------------------------------------
123 | 345 | David | Davidson | 3 | Denmark
------------------------------------------------------
678 | 981 | Edwin | N/A | 4 | Equador
------------------------------------------------------
Любая помощь или совет будут оценены по достоинству.
Комментарии:
1. Я не уверен, о чем вы спрашиваете, но ключи в словаре python не упорядочены. Если вы хотите, чтобы он вел себя как список, вам нужно использовать OrderedDict вместо dict. docs.python.org/3/library/. …
2. Что вы сделали до сих пор? Вы не показали нам никакого кода для отладки.
3. @shrewmouse, это было верно до python3.6. Затем в качестве детали реализации была введена функция сохранения порядка . Начиная с 3.7 эта функция гарантируется для регулярных диктовок. И в любом случае неясно, имеет ли это отношение к вопросу в любом случае.
4. @shrewmouse извините, вы правы — всего секунду. Re. OrderedDict, я попробовал, и он возвращается с ошибкой : «Ошибка значения: слишком много значений для распаковки (ожидается 2)»
5. @буран порядок не важен в диктанте. Важно только, чтобы значения были помещены в правильные поля и не сдвигались, если ключа не существует
Ответ №1:
Вы можете реализовать цикл, подобный этому.
fmtstr = "{:<4} | {:<6} | {:<8} | {:<8} | {:^6} | {:<8}"
line = "--------------------------------------------------------"
print(fmtstr.format(*my_list))
print(line)
for entry in my_dict:
id_ = entry.get('_id')
count = entry.get('count')
for nentry in entry.get('account', []):
print(fmtstr.format(id_,
count,
nentry.get('f_name', 'N/A'),
nentry.get('l_name', 'N/A'),
nentry.get('number', 'N/A'),
nentry.get('country', 'N/A')))
print(line)
Используя ваши данные, вывод будет:
_id | count | f_name | l_name | number | country
--------------------------------------------------------
123 | 345 | Adam | Adamson | 1 | Argentina
--------------------------------------------------------
123 | 345 | N/A | Charlson | N/A | Canada
--------------------------------------------------------
123 | 345 | David | Davidson | 3 | Denmark
--------------------------------------------------------
678 | 981 | Edvin | N/A | 4 | Equador
--------------------------------------------------------
Если вам нужны данные в формате CSV, решение будет проще:
print(','.join(my_list))
for entry in my_dict:
id_ = entry.get('_id')
count = entry.get('count')
for nentry in entry.get('account', []):
print(("{},{},{},{},{},{}"
.format(id_,
count,
nentry.get('f_name', 'N/A'),
nentry.get('l_name', 'N/A'),
nentry.get('number', 'N/A'),
nentry.get('country', 'N/A'))))
На этот раз результат будет:
_id,count,f_name,l_name,number,country
123,345,Adam,Adamson,1,Argentina
123,345,N/A,Charlson,N/A,Canada
123,345,David,Davidson,3,Denmark
678,981,Edvin,N/A,4,Equador
Комментарии:
1. Спасибо, это помогает в качестве отправной точки, вывод должен быть внутри csv. Моя проблема в том, что каждый раз, когда значение отсутствует, оно смещается в сторону и не пишет «N/A»
2. Вы имеете в виду, что выходные данные должны быть в формате CSV?
3. Точно. Я пытался понять, как я могу получить доступ к ключевым значениям и расположить их в правильном порядке, так как в CSV они постоянно меняются. И я должен жестко закодировать имена заголовков / полей, потому что в противном случае они будут расположены в неправильном порядке, если в первом объекте чего-то не хватает
4. Я думаю, что вы никогда не найдете решения, которое работает для общего словаря. Если вы считаете, что некоторые дополнительные ключи могут присутствовать в будущей версии данных, просто добавьте сканирование, чтобы проверить наличие всех ключей, и инициализируйте массив
my_list
во время сканирования.
Ответ №2:
Как только вы исправите опечатки в своем списке и словаре, вы сможете преобразовать словарь в таблицу (список списков) и экспортировать его с помощью модуля csv:
table = [ [d.get(k,a.get(k,'N/A')) for k in my_list]
for d in my_dict for a in d['account'] ]
Выход:
for row in table:print(row)
[123, 345, 'Adam', 'Adamson', 1, 'Argentina']
[123, 345, 'N/A', 'Charlson', 'N/A', 'Canada']
[123, 345, 'David', 'Davidson', 3, 'Denmark']
[678, 981, 'Edvin', 'N/A', 4, 'Equador']
Затем сохраните в csv-файл:
import csv
with open('table.csv','w') as f:
output = csv.writer(f)
output.writerow(my_list)
for row in table:
output.writerow(row)
Из довольно печатной таблицы:
for row in [my_list,*table]:
print("|".join(f" {str(c):10}" for c in row))
print("-"*70)
_id | count | f_name | l_name | number | country
----------------------------------------------------------------------
123 | 345 | Adam | Adamson | 1 | Argentina
----------------------------------------------------------------------
123 | 345 | N/A | Charlson | N/A | Canada
----------------------------------------------------------------------
123 | 345 | David | Davidson | 3 | Denmark
----------------------------------------------------------------------
678 | 981 | Edvin | N/A | 4 | Equador
----------------------------------------------------------------------