1 问题
你希望针对字典中的数据执行各种计算操作(例如:最大值、最小值、排序等等)。
2. 解决方案
假定现有下列字典,字典的每一项建立了股票名和股价的映射:
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75,
}
为了可以方便地对字典数据进行计算,通过需要使用 zip 类将字典中的键和值进行翻转。例如,下面基于此结合 min() 和 max( ) 函数查找到了最低和最高股价及对应股票名称:
>>> min_price = min(zip(prices.values(), prices.keys()))
>>> min_price
(10.75, 'FB')
>>> max_price = max(zip(prices.values(), prices.keys()))
>>> max_price
(612.78, 'AAPL')
类似地,也可以结合 zip 类和 sorted 函数对数据进行排序,例如:
>>> prices_sorted = sorted(zip(prices.values(), prices.keys()))
>>> prices_sorted
[(10.75, 'FB'), (37.2, 'HPQ'), (45.23, 'ACME'), (205.55, 'IBM'), (612.78, 'AAPL')]
需要特别注意的是,通过 zip 类创建的对象是一个迭代器,该迭代器只能被接收可迭代对象为参数的类或函数消费一次,否则会产生错误。例如:
>>> prices_and_names = zip(prices.values(), prices.keys())
>>> print(min(prices_and_names))
(10.75, 'FB')
>>> print(max(prices_and_names))
Traceback (most recent call last):
File "<input>", line 1, in <module>
ValueError: max() arg is an empty sequence
3. 讨论
需要特别注意的是,如果你直接针对字典对象进行上述类似计算,那么你会发现执行的结果是针对字典所有的键而不是值。例如:
>>> max(prices)
'IBM'
>>> min(prices)
'AAPL'
为了避免上述情况,你可以通过调用字典对象的 values() 方法来解决:
>>> min(prices.values())
10.75
>>> max(prices.values())
612.78
然而,这可能也不是你最终需要的,你最终需要的可能是股价最低或最高的股票的名称。对此,你可以通过为 min() 或 max() 函数的形参 key 指定一个函数作为实参来得到股价最小值或最大值对应的股票名称(即字典中每一条记录的键)。例如:
>>> min(prices, key=lambda k: prices[k])
'FB'
>>> max(prices, key=lambda k: prices[k])
'AAPL'
如果你希望得到股价的最小值或最大值,你可以继续这么做:
>>> min_value = prices[min(prices, key=lambda k: prices[k])]
>>> min_value
10.75
因此,为了避免上述这么复杂的逻辑,本文一开始就使用了 zip 来将字典中的键值对转化为 (value, key) 元组形式的序列对。当对元组进行比较时,元组的 value 会被先行比较,然后是比较 value ,这样一来就可以直接使用 min() 、 max() 以及 sorted() 函数了,也不用指定参数 key 了。
|