Проверьте, совпадает ли ключ вложенного словаря с элементом в списке

#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   
----------------------------------------------------------------------