Python进阶编程:编写更高效、优雅的Python代码
上QQ阅读APP看书,第一时间看更新

3.2.4 字典运算

字典是key-value形式的对象,要对字典中的value求最小值、最大值、排序等,该如何操作呢?

以下是课程与得分字典示例,相关代码(dict_calculation.py)如下:


course_score = {
    '高等代数': 100.0,
    '算法与数据结构': 92.0,
    '编译原理': 88.5,
    '数学分析': 97.5,
    '统计学原理': 90.5
}

为了对字典值执行计算操作,通常需要使用zip()函数先将键和值反转过来。以下是查找最高和最低得分和课程名称的代码(dict_calculation.py):


min_score = min(zip(course_score.values(), course_score.keys()))
print(f'最低得分课程及得分:{min_score[1]} {min_score[0]}')
max_score = max(zip(course_score.values(), course_score.keys()))
print(f'最高得分课程及得分:{max_score[1]} {max_score[0]}')

执行py文件,可以看到输出结果如下:


最低得分课程及得分:编译原理 88.5
最高得分课程及得分:高等代数 100.0

类似地,我们可以使用zip()和sorted()函数来排列字典数据,即在py文件中添加如下代码(dict_calculation.py):


score_sorted = sorted(zip(course_score.values(), course_score.keys()))
print(score_sorted)

需要注意的是,zip()函数创建的是一个只能访问一次的迭代器。若写成如下形式,代码就会产生错误:


score_and_course = zip(course_score.values(), course_score.keys())
# ok,print is normal
print(min(score_and_course))
# ValueError: max() arg is an empty sequence
print(max(score_and_course))

在一个字典上执行普通的数学运算,它们会仅作用于键,而不是值,示例如下:


print(min(course_score)) # 数学分析
print(max(course_score)) # 高等代数

这个结果并不是我们所期望的,因为期望的是在字典集合上执行这些计算。或许我们可以尝试使用字典的values()方法来解决这个问题,示例如下:


print(min(course_score.values())) # 88.5
print(max(course_score.values())) # 100.0

不幸的是,这个结果同样也不是我们所期望的,因为我们还要知道对应的键的信息(比如哪门课程的分数是最低的)。

可以在min()和max()函数中提供key参数来获取最小值或最大值对应的键的信息,示例如下:


print(min(course_score, key=lambda k: course_score[k])) # 编译原理
print(max(course_score, key=lambda k: course_score[k])) # 高等代数

但若还想要得到最小值,得再执行一次查找操作,示例如下:


min_score = course_score[min(course_score, key=lambda k: course_score[k])]
print(min_score)

前面的zip()函数通过将字典反转为(值,键)元组序列,可以很方便地解决上述问题。

当比较两个元组的时候,首先比较值,然后比较键。这样能通过一条简单的语句很轻松地在字典中实现求最值和排序操作。

注意 在计算操作中使用了(值,键)对,当多个实体拥有相同的值的时候,键会决定返回结果。如在执行min()和max()运算的时候,如果恰巧最小或最大值有重复,那么返回拥有最小或最大键的实体。