数据结构和算法-8-字典的运算

问题描述

1
2
3
4
5
6
7
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}

怎样在数据字典中执行一些计算操作(比如求最小值、最大值、排序等等)?

解决方案

STEP1. 把「键」和「值」反转,方便对比值的大小。

STEP2. 使用 min() 、max()、sorted() 进行操作。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
def test_data_dict_operate():
"""数据字典的操作,求最大、最小值,排序等"""
prices = {
'ACME': 45.23,
'AAPL': 612.78,
'IBM': 205.55,
'HPQ': 37.20,
'FB': 10.75
}

# 字典上执行普通的数学运算,它们仅仅作用于键
assert min(prices) == 'AAPL'
assert max(prices) == 'IBM'

# 但这不是我们想要的,我们想要的是值
# 于是我们尝试使用 values 获得值
assert min(prices.values()) == 10.75
assert max(prices.values()) == 612.78

# 可是光有值也不行啊,我们想要的是键和值对应起来,这样才更清晰
# 于是
# 在 min() 和 max() 函数中提供 key 函数参数来获取最小值或最大值对应的键的信息
assert min(prices, key=lambda k: prices[k]) == 'FB'
assert max(prices, key=lambda k: prices[k]) == 'AAPL'

# 可键的信息是有了,值的信息还得再查找一次
# 于是
assert prices[min(prices, key=lambda k: prices[k])] == 10.75
assert prices[max(prices, key=lambda k: prices[k])] == 612.78

# 太麻烦了,有没有简单一点的?

# 有!

# STEP1. 使用zip()将字典转换为一个以元组为元素的列表,注意值(数据)在前面了
new_prices = zip(prices.values(), prices.keys())
# STEP2. 使用min()取出最小值
assert min(new_prices) == (10.75, 'FB')

# STEP1. 由于zip() 函数创建的是一个只能访问一次的迭代器,因此我们还得再创建一次
new_prices = zip(prices.values(), prices.keys())
# STEP2. 使用max()取出最小值
assert max(new_prices) == (612.78, 'AAPL')

# 上面的例子这样写会更好:
assert min(zip(prices.values(), prices.keys())) == (10.75, 'FB')
assert max(zip(prices.values(), prices.keys())) == (612.78, 'AAPL')

# 排序可以使用 zip + sorted
assert sorted(zip(prices.values(), prices.keys())) == [(10.75, 'FB'), (37.2, 'HPQ'), (45.23, 'ACME'),
(205.55, 'IBM'), (612.78, 'AAPL')]

注意:

当多个「」拥有相同的时候,「键」会决定返回结果。

比如,在执行 min()max() 操作的时候,如果恰巧最小或最大值是相同的,那么将按照键的大小进行对比:

1
2
3
4
5
6
7
> >>> prices = { 'AAA' : 45.23, 'ZZZ': 45.23 }  # 值是相同的
> >>> min(zip(prices.values(), prices.keys())) # 值相同时按键进行对比
> (45.23, 'AAA')
> >>> max(zip(prices.values(), prices.keys()))
> (45.23, 'ZZZ')
> >>>
>
毕小烦 wechat
「请扫一扫上面的二维码,关注老毕的微信公众号」
「您的赞赏是老毕持续创作的动力」