上QQ阅读APP看书,第一时间看更新
3.2.2 字典映射
在实际应用中,一个键对应一个值的映射不能满足所有需求,有时需要通过一个关键值获取多个值,即一个键对应多个值。
字典是一个键对应单值的映射。如果想要一个键映射多个值,只需将多个值放到另外的容器中,比如列表或者集合里,再通过一个键获取该列表或集合即可。比如,可以像下面这样构造对应的字典:
exp_dict_1 = { 'a': [1, 3, 5], 'b': [2, 4] } exp_dict_2 = { 'a': {'a', 'b', 'c'}, 'b': {'c', 'd'} } exp_dict_3 = { 'a': {'b': '1'}, 'b': {'c': 2} }
选择使用列表还是集合取决于实际应用需求。
如果想保持元素的插入顺序就应该使用列表;如果想去掉重复元素可以使用Set集合,但Set集合不保证元素的顺序;使用字典可以去掉重复的key,字典也是无序的。不过,collections模块中提供了一个OrderedDict类,该类可以保证字典的顺序。
我们可以使用collections模块中的defaultdict来构造字典。defaultdict的一个特征是它会自动初始化每个key刚开始对应的值,我们只需要关注添加元素的操作,示例如下:
from collections import defaultdict default_dict = defaultdict(list) default_dict['a'].append(1) default_dict['b'].append(3) default_dict = defaultdict(set) default_dict['a'].add(1) default_dict['b'].add(2)
注意 defaultdict会自动为将要访问的键(就算目前字典中并不存在这样的键)创建映射实体。如果不需要这样的特性,可以在一个普通的字典上使用setdefault()方法来代替,示例如下:
d_dict = dict() d_dict.setdefault('a', []).append(1) d_dict.setdefault('b', []).append(2)
不过,很多程序员觉得setdefault()方法用起来有点别扭,因为每次调用都得创建一个新的初始值的实例(如示例中的空列表[])。
一般来讲,创建一个多值映射字典是很简单的。但如果选择自己实现,值的初始化编写代码会更多,并且可读性会降低。我们可以使用如下方式编写代码:
# 原始手动方式 define_dict = dict() for key, value in key_value_items: if key not in define_dict: define_dict[key] = [] define_dict[key].append(value)
使用defaultdict精简后代码如下:
# 改进实现方式 define_dict = defaultdict(list) for key, value in key_value_items: define_dict[key].append(value)
由示例代码可见,使用defaultdict后,代码量少,代码更具可读性。所以,建议读者在工作中尽量用defaultdict代替手动实现。