【问题标题】:Check if nested dictionary key same as item in list检查嵌套字典键是否与列表中的项目相同
【发布时间】:2021-11-12 07:33:47
【问题描述】:

对于大多数人来说,这可能是一个超级简单的问题,但有困难的学生会很感激一些帮助。 我有一本包含嵌套字典列表的字典。 部分商品丢失或顺序错误。

我正在尝试以特定顺序将其导出为 csv(列表) 我需要比较列表键名中的项目并返回值。如果key不存在返回'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
------------------------------------------------------


任何帮助或建议将不胜感激。

【问题讨论】:

  • 我不确定你在问什么,但 python 字典中的键没有排序。如果你想让它表现得像一个列表,你需要使用 OrderedDict 而不是 dict。 docs.python.org/3/library/….
  • 到目前为止你做了什么?您还没有显示任何代码供我们调试。
  • @shrewmouse,这在 python3.6 之前是真的。然后order-preserving feature was introduced as an implementation detail。从 3.7 开始,此功能保证适用于常规 dicts。无论如何,尚不清楚它是否与 OP 问题有关。
  • @shrewmouse 对不起,你是对的 - 等一下。回覆。 OrderedDict,我试过了,它返回一个错误:“ValueError:解包的值太多(预期 2)”
  • @buran 的顺序在字典中并不重要。仅重要的是,将值放置在正确的字段中,并且如果键不存在则不要移动

标签: python list dictionary nested


【解决方案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

【讨论】:

  • 谢谢,这有助于作为一个起点输出应该在 csv 中。我的问题是,每次缺少一个值时,它都会移到一边并且不写'N/A'
  • 你的意思是输出应该是CSV格式?
  • 没错。我试图了解如何访问键值并将它们按正确的顺序放置,因为在 CSV 上它一直在变化。而且我必须对标题/字段名称进行硬编码,否则如果第一个对象中缺少某些内容,它将采用错误的顺序
  • 我认为您永远找不到适用于通用字典的解决方案。如果您认为未来版本的数据中可能存在一些额外的键,只需添加扫描以检查所有键并在扫描期间初始化数组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   
----------------------------------------------------------------------

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-04
    • 2022-01-22
    • 1970-01-01
    • 2021-02-28
    • 2015-06-02
    相关资源
    最近更新 更多