首页 > 解决方案 > 将包含多个嵌套字典的字典转换为 .csv

问题描述

我在 Python 中有一个包含多个嵌套字典的字典,我想将它们写入一个 csv 文件。

字典看起来像这样:

dict = {'case1':{'variant1':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}},
                 'variant2':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']},
        'case2':{'variant1':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}},
                 'variant2':{'Name':['1','2','3'],'Values':[1,2,3],'Unit':['one','two','three']}}

因此,具有不同变体的多个案例,每个变体包含三个对应名称、值和单位的列表。如前所述,我想将此 dict 转换为 csv 文件,理想情况下,不同情况下的变体很容易区分。由于 csv 将主要在 Excel 中使用,我将举例说明我想象它在 Excel 中的外观。理想是这样的: test_dict2csv

我知道如何将单个变体(因此一组名称、值和单位)写入 csv,其代码如下所示:

keys = sorted(dict['case1']['variant1'].keys())
with open("test_output.csv", "w") as outfile:
   writer = csv.writer(outfile,delimiter=';')
   writer.writerow(keys)
   writer.writerows(zip(*[dict['case1']['variant1'][key] for key in keys]))

但我不知道如何在同一行向下添加下一个变体和案例。

如果有人有想法,我将不胜感激:)

标签: pythoncsvdictionarynested

解决方案


如果要为每个元素生成一条记录,每个列表中生成一个元素,可以先展平字典,然后像这样编写:

import csv
from pprint import pprint

dict_data = {
    "c1": {
        "v1": {
            "Name": ["s111", "s112", "s113"],
            "Values": [111, 112, 113],
            "Unit": ["11one", "11two", "11three"],
        },
        "v2": {
            "Name": ["s121", "s122", "s123"],
            "Values": [121, 122, 123],
            "Unit": ["12one", "12two", "12three"],
        },
    },
    "c2": {
        "v1": {
            "Name": ["s211", "s212", "s213"],
            "Values": [211, 212, 213],
            "Unit": ["21one", "21two", "21three"],
        },
        "v2": {
            "Name": ["s221", "s222", "s223"],
            "Values": [221, 222, 223],
            "Unit": ["22one", "22two", "22three"],
        },
    },
}


def flatten_dict(curr_dict, curr_key=""):
    new_dict = {}
    for new_key, value in curr_dict.items():

        if curr_key == "":
            combined_key = new_key
        else:
            combined_key = curr_key + "_" + new_key

        if isinstance(value, dict):
            new_dict.update(flatten_dict(value, combined_key))
        else:
            new_dict[combined_key] = value

    return new_dict


flat = flatten_dict(dict_data)
pprint(flat)


keys = sorted(flat.keys())
with open("test_output_all.csv", "w") as outfile:
    writer = csv.writer(outfile, delimiter=";")
    writer.writerow(keys)
    writer.writerows(zip(*[flat[key] for key in keys]))

(我只是将 dict 更改为更清楚哪个值是哪个,并且键名更短,结构与您的相似)。这打印:

{'c1_v1_Name': ['s111', 's112', 's113'],
 'c1_v1_Unit': ['11one', '11two', '11three'],
 'c1_v1_Values': [111, 112, 113],
 'c1_v2_Name': ['s121', 's122', 's123'],
 'c1_v2_Unit': ['12one', '12two', '12three'],
 'c1_v2_Values': [121, 122, 123],
 'c2_v1_Name': ['s211', 's212', 's213'],
 'c2_v1_Unit': ['21one', '21two', '21three'],
 'c2_v1_Values': [211, 212, 213],
 'c2_v2_Name': ['s221', 's222', 's223'],
 'c2_v2_Unit': ['22one', '22two', '22three'],
 'c2_v2_Values': [221, 222, 223]}

在文件中:

c1_v1_Name;c1_v1_Unit;c1_v1_Values;c1_v2_Name;c1_v2_Unit;c1_v2_Values;c2_v1_Name;c2_v1_Unit;c2_v1_Values;c2_v2_Name;c2_v2_Unit;c2_v2_Values
s111;11one;111;s121;12one;121;s211;21one;211;s221;22one;221
s112;11two;112;s122;12two;122;s212;21two;212;s222;22two;222
s113;11three;113;s123;12three;123;s213;21three;213;s223;22three;223

如果您绝对需要图片中的标题,则应该对标题行进行一些预处理,以便在单独的行上打印每个嵌套级别。

干杯!


推荐阅读