嵌套字典列表

5

我有三个对象,需要将它们填充到JSON文件格式中。这些对象来自一个API,需要进行展开以进行访问,如下所示:

my_dict = {}
for elem_a in list_a:
    for elem_b in elem_a:
        for elem_c in elem_b:
            elem_c_info = {
                "name" : elem_c.prop1,
                "ID" : elem_c.prop2,
                "GPA" : elem_c.prop3
            }

            my_dict.setdefault("university", {}) \
                 .setdefault(str(elem_a), {}) \
                 .setdefault(str(elem_b), {}) \
                 .setdefault("student", []).append(elem_c_info)

产生以下输出内容:
{
    "university": {
        "universityA": {
            "class_1": {
                "student": [
                    {
                        "name": "student_1", 
                        "ID": "1234", 
                        "GPA": "3.8"
                        },

我的期望输出:

{
    "university": [{
        "name": "universityA",
        "class": [{
                "name": "class_1",
                "student": [{
                        "name": "student_1",
                        "ID": "1234",
                        "GPA": "3.8"
                    },
                    {
                        "name": "student_2",
                        "ID": "12345",
                        "GPA": "3.4"
                    }
                ]
            },
            {
                "name": "class_2",
                "student": [{
                    "name": "student_3",
                    "ID": "14",
                    "GPA": "3.0"
                }]
            }
        ]
    }]
}

如您所见,我需要每个嵌套的字典在每个层级上都被放入一个列表中,并且我需要在每个层级(除了最内层)添加一个键/值对。我通过使用`.append`成功地处理了最内层的嵌套,但在更高层次上却没有运行。您有什么关于向数据结构添加这些元素的建议吗?接受解决这两个问题的方案。
以下是运行简单嵌套循环时输入数据结构的样子(感谢@PM_2Ring的建议):
在我上面的示例中:
list_a = [obj_1, obj_2, ..., obj_n]  

for elem_a in list_a:
    print('A', elem_a.name)
    for elem_b in elem_a:
        print('  B', elem_b.name)
        for elem_c in elem_b:
            print('    C', elem_c.prop1, elem_c.prop2, elem_c.prop3)

('A', universityA)
('  B', class_1)
('    C', student_1, 12345, 3.8)
('  B', class_2)
('    C', student_2, 145, 3.6)
('A', universityB)
('  B', class_1)
('    C', student_1, 12345, 3.8)
('    C', student_2, 1235, 3.6)
('    C', student_3, 12345, 3.4)
('  B', class_2)
('    C', student_1, 145, 3.6)
  ....

elem_a = [universityA, universityB, universityC]  # Top tier
elem_b = [universityA.class_1, universityA.class_2, universityA.class_3]              # Middle tier with OO property 'name'
elem_c = [universityA.class_1.student_name, universityA.class_1.student_id, universityA.class_1.student_gpa]  # bottom tier relationship

1
我很惊讶你的上一个代码能够工作。elem_a_prop变量未定义。此外,我无法理解你期望的最终结果是什么,我怀疑你需要在字典中增加列表而不是字典本身,即my_dict['list_a'] += {'name': ....}。 - Serge
@Serge,将特定领域术语翻译成通用形式存在一些问题。我会详细说明我的意思。在你提到的情况中,实际上应该是str(elem_a.elem_a_prop)。 - Shawn
@Shawn,你只展示了list_a中单个元素的预期输出,请更新多个元素的输出。 - Grigoriy Mikhalkin
1
更新了原始帖子信息。 - Shawn
1个回答

1

我觉得你的方法失败了,因为你试图一次性完成所有事情:那个一行赋值语句相当复杂。相反,考虑使用类似以下的方式:

my_dict = {}
list_result = []
for elem_a in list_a:
    elem_a_result = []
    for elem_b in elem_a:
        elem_b_result = []
        for elem_c in elem_b:
            elem_b_result.append({
                'prop1': elem_c.prop1,
                'prop2': elem_c.prop2,
                'prop3': elem_c.prop3,
            })
        elem_a_result.append({
            'name': elem_b.name,
            'elem_b': elem_b_result,
        })
    list_result.append({
        'name': elem_a.name,
        'elem_a': elem_a_result
    })
my_dict = {
    'list_a': list_result
}

你可以让每个for循环中的代码仅在你的结构的特定级别上工作,而不必关心整体情况。
注意:我没有测试过这个,因为我无法访问像你的数据格式(带有属性和迭代等)那样的数据。
经过一段时间的思考,我发现这可以很容易地重写为一个巨大的列表推导式。然而,这是否更易读是值得怀疑的。它看起来更加清晰,形状类似于目标结构,但比直接使用for循环版本更加复杂。
my_dict = {
    'list_a': [
        {
            'name': elem_a.name,
            'elem_a': [
                {
                    'name': elem_b.name,
                    'elem_b': [
                        {
                            'prop1': elem_c.prop1,
                            'prop2': elem_c.prop2,
                            'prop3': elem_c.prop3,
                        }
                    for elem_c in elem_b]
                }
            for elem_b in elem_a]
        }
    for elem_a in list_a]
}

1
你真是个救命恩人!!!根据我快速转换到域API,这正好给了我想要的结果。谢谢! - Shawn
@Shawn 不用谢。我添加了另一个版本……以防你喜欢嵌套列表推导式。 - Norrius

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接