如何使用dict理解创建字典词典?

时间:2018-01-12 09:51:20

标签: python list dictionary list-comprehension

我正在尝试使用列表列表中的字典理解来创建字典字典。

列表列表包含学生姓名,作业名称和成绩。例如,数据可能如下所示:

grades_lists = [
    ['Student', 'Test', 'Assignment', 'Exam'],
    ['Bella', '80', '90', '100'],
    ['Sam', '65', '75', '85'],
    ['Emily', '60', '75', '90'],
]

我想创建一个字典,将学生姓名映射到包含作业名称和成绩的字典。例如:

grades_dicts['Bella']['Test'] == 80

我想要的字典是:

{
    'Bella': {'Test': 80, 'Assignment': 90, 'Exam': 100},
    'Sam': {'Test': 65, 'Assignment': 75, 'Exam': 85},
    'Emily': {'Test': 60, 'Assignment': 75, 'Exam': 90}
}

因此grades_list中的每一行都成为字典;第一列是学生的名字,其他列是字典中的值,其中的键取自grades_list的第一行。

我一直在尝试使用dict理解来生成字典中的相应键和值。像这样:

grade_dicts = {x[0]:{y:z} for y in grades_lists[0][1:] for x in grades_lists[1:] for z in x[1:]}

但这并没有正确生成所有成绩:

{
    'Bella': {'Exam': '100'},
    'Emily': {'Exam': '90'},
    'Sam': {'Exam': '85'}
}

1 个答案:

答案 0 :(得分:4)

你的巢穴混乱了。以下作品:

{name: {col: int(value) for col, value in zip(grades_list[0][1:], row)}
 for name, *row in grades_list[1:]}

for name, *row in ...循环占用每一行,只将第一个值提取到name,余数提取到row*告诉Python取余数)。这使您可以将该行与第一行中的列名一起使用来创建嵌套字典。

通过使用常规循环,通常更容易看到理解的作用。您的代码执行此操作:

grade_dicts = {}
for y in grades_lists[0][1:]:
    for x in grades_lists[1:]:
        for z in x[1:]:
            grade_dicts[x[0]] = {y:z}

那种循环太多了,你最终会为x[0]多次设置一个值;事实上len(x[1:])次。只剩下最后一个{y: z}字典。

我的版本执行此操作:

grade_dicts = {}
for name, *row in grades_list[1:]:
    inner = {}
    for col, value in zip(grades_list[0][1:], row):
        inner[col] = int(value)
    grade_dicts[name] = inner

这只是两个循环,其中内部为每列产生一个单独的字典。我使用zip()配对标签和值。