记录几个 Python 字典中的冷门操作

作者: 王炳明 分类: Python 基础教程 发布时间: 2021-01-18 22:25 热度:41

01. 键映射多个值

一个字典就是一个键对应一个单值的映射。如果你想要一个键映射多个值,那么你就需要将这多个值放到另外的容器中, 比如列表或者集合里面。比如,你可以像下面这样构造这样的字典:

d = {
    'a' : [1, 2],
    'b' : [3]
}
e = {
    'a' : {1, 2},
    'b' : {3}
}

按照常规的做法,你可能会这么做

d=dict()
d.setdefault('a',[]).append(1)
d.setdefault('a',[]).append(2)
d.setdefault('b',[]).append(3)

e=set()
e.setdefault('a',{}).add(1)
e.setdefault('a',{}).add(2)
e.setdefault('b',{}).add(3)

在这里有一种更加优雅的做法

from collections import defaultdict

d = defaultdict(list)
d['a'].append(1)
d['a'].append(2)
d['b'].append(4)

d = defaultdict(set)
d['a'].add(1)
d['a'].add(2)
d['b'].add(4)

02. 有顺序的字典

大家都知道,字典是无序的。但是不排除某些情况下,我们会需要让字典变得有序,比如序列化成字符串时。

在 collects 中同样也提供了一个数据结构(OrderedDict),来实现这个需求。

from collections import OrderedDict

d = OrderedDict()
d['foo'] = 1
d['bar'] = 2
d['spam'] = 3
d['grok'] = 4

for k in d:
    print(k, d[k])

import json
json.dumps(d)

输出如下

('foo', 1)
('bar', 2)
('spam', 3)
('grok', 4)

'{"foo": 1, "bar": 2, "spam": 3, "grok": 4}'

OrderedDict 内部维护着一个根据键插入顺序排序的双向链表。每次当一个新的元素插入进来的时候, 它会被放到链表的尾部。对于一个已经存在的键的重复赋值不会改变键的顺序。

需要注意的是,一个 OrderedDict 的大小是一个普通字典的两倍,因为它内部维护着另外一个链表。 所以如果你要构建一个需要大量 OrderedDict 实例的数据结构的时候(比如读取 100,000 行 CSV 数据到一个 OrderedDict 列表中去), 那么你就得仔细权衡一下是否使用 OrderedDict 带来的好处要大过额外内存消耗的影响。

03. 键值的反转

首先需要了解了 zip 这个函数就好了。他可以将两个列表(当然其他用途不止两个,这里只是针对字典)重新组合。最后使用 dict 转换为字典。

>>> keys = ['name', 'age', 'food']
>>> values = ['Monty', 42, 'spam']
>>>
>>> zip(keys, values)
[('name', 'Monty'), ('age', 42), ('food', 'spam')]
>>>
>>> dict(zip(keys, values))
{'food': 'spam', 'age': 42, 'name': 'Monty'}

理解了 zip ,键值的反转,就变得容易了。只要把key和values的位置对调一下即可。

>>> d={'food': 'spam', 'age': 42, 'name': 'Monty'}
>>> zip(d.values(), d.keys())
[('spam', 'food'), (42, 'age'), ('Monty', 'name')]
>>>
>>> dict(zip(d.values(), d.keys()))
{42: 'age', 'Monty': 'name', 'spam': 'food'}

04. 求最大值对应的键

假设现在有一个字典,里面存放着众多水果的价格。

>>>prices={"Apple": 6, "Mango": 7, "Pear":3}

现在要找出,哪一种水果是最贵的。你会发现不太好找

一种思路是,可以借助上面的zip,将value调到前面来,再max

>>> max(zip(prices.values(), prices.keys()))
(7, 'Mango')

但是始终不太优雅。
这里还可以这样使用max函数。

>>> max(prices, key=lambda k:prices[k])
'Mango'
weixin

文章有帮助,请作者喝杯咖啡?

发表评论

电子邮件地址不会被公开。 必填项已用*标注