1.6 字典中的键映射多个值¶

问题¶

怎样实现一个键对应多个值的字典(也� multidict)?

解决方案¶

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

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

选择使用列表还是集��决于你的实际需求。如果你想��元素的�入顺�就应该使用列表, 如果想去掉��元素就使用集�(并且�关心元素的顺�问题)。

你�以很方便的使用 collections 模�中的 defaultdict �构造这样的字典。 defaultdict 的一个特�是它会自动�始化�个 key 刚开始对应的值,所以你�需�关注添加元素�作了。比如:

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)

需�注�的是, defaultdict 会自动为将�访问的键(就算目�字典中并�存在这样的键)创建映射实体。 如果你并�需�这样的特性,你�以在一个普通的字典上使用 setdefault() 方法�代替。比如:

d = {} # 一个普通的字典
d.setdefault('a', []).append(1)
d.setdefault('a', []).append(2)
d.setdefault('b', []).append(4)

但是很多程�员觉得 setdefault() 用起�有点别扭。因为�次调用都得创建一个新的�始值的实例(例�程�中的空列表 [] )。

讨论¶

一般�讲,创建一个多值映射字典是很简�的。但是,如果你选择自己实现的�,那么对于值的�始化�能会有点麻烦, 你�能会�下�这样�实现:

d = {}
for key, value in pairs:
    if key not in d:
        d[key] = []
    d[key].append(value)

如果使用 defaultdict 的�代�就更加简�了:

d = defaultdict(list)
for key, value in pairs:
    d[key].append(value)

这一�节所讨论的问题跟数�处�中的记录归类问题有大的关�。�以�考 1.15 �节的例�。