一、与字典值有关的计算
问题
想对字典的值进行相关计算,例如找出字典里对应值最大(最小)的项。
解决方案一:
假设要从字典 {'a':3, 'b':2, 'c':6} 中找出值最小的项,可以这样做:
> d = {'a':3, 'b':2, 'c':6} > min(zip(d.values(), d.keys())) (2, 'b')
值得注意的是 d.values() 获取字典的全部值,d.keys()
获取字典的全部键,而且两个序列的顺序依然保持一一对应的关系。因此 zip(d.values() , d.keys())
实质上生成的是一个 (value, key) 的序列。min 函数通过比较序列中的元组 (value, key) 找出其最小值。
解决方案二:
除了使用 zip(d.values() , d.keys())
外,还可以使用 dict.items()
方法和生成器推导式来生成 (value, key) 序列,从而传递给 min 函数进行比较:
> d = {'a':3, 'b':2, 'c':6} > min((v ,k) for (k, v) in d.items()) (2, 'b')
这里 min 函数的参数 (v ,k) for (k, v) in d.items()
其实是一个生成器推导式(和列表推导式一样,只是把列表推导式的 [] 改为 () ,而且其返回的一个生成器而非列表),由于生成器推导式做为 min 函数的参数,所以可以省略掉两边的括号(不做为参数时写法应该是 ((v ,k) for (k, v) in d.items()) )
。
二、字典推导式
问题
想把一个元组列表转换成一个字典,例如把 [('a', 1), ('b', 2), ('c', 3)]
转化为 {'a': 1, 'b': 2, 'c': 3}
解决方案
类似于列表推导式,字典推导式可以方便地从其他数据结构构造字典,例如:
> l = [('a', 1), ('b', 2), ('c', 3)] > {k: v for k, v in l} {'c': 3, 'b': 2, 'a': 1}
字典推导式的规则和列表推导式一样,只是把 [] 换成 {}
三、寻找字典的交集
问题
假设有两个字典:
d1 = {'a':1, 'b':2, 'c':3, 'd':4} d2 = {'b':2, 'c':3, 'd':3, 'e':5}
要找出这两个字典中具有公共键的项,即要得到结果 {'b':2, 'c':3}
解决方案
我们知道一般通过 d.items()
方法来遍历字典,d.items()
方法返回的对象是一个类集合对象,支持集合的基本运算,如取交集、并集等。
> dict(d1.items() & d2.items()) # 取交集 {'b': 2, 'c': 3}
此外,d.keys()
返回字典的键,也是一个类集合对象,如果我们只想找出两个字典中键相同的项,可以这样:
> { k:d1[k] for k in d1.keys() & d2.keys() } {'b': 2, 'd': 4, 'c': 3}
这里如果相同的键对应不同的值则去第一个字典中的值。推广开来,如果想排除掉字典中的某些键,可以这样:
> { k:d1[k] for k in d1.keys() - {'c', 'd'} } # - 号的含义是集合的差集操作 {'b': 2, 'a': 1}
但有一点需要注意的是,d.values()
返回字典的值,由于字典对应的值不一定唯一,所以 d.values()
一般无法构成一个集合,因此也就不支持一般的集合操作。
四、多个字典连接成一个字典
问题
有多个字典,例如:
d1 = {'a':1, 'b':2, 'c':3} d2 = {'c':4, 'd':5, 'e':6}
想将这多个字典连接为一个字典,或一次性对多个字典进行迭代操作。
解决方案
使用 collections.ChainMap
:
> from collections import ChainMap > chain_dict = ChainMap(d1, d2) > for k, v in chain_dict.items(): print(k, v) a 1 e 6 d 5 c 3 b 2
ChainMap 将传入的多个字典连接为一个字典,并返回一个 ChainMap 对象,这个对象的行为就像一个单一的字典,我们可以对其进行取值或者迭代等操作。注意到这里键 c 对应的值为 3,如果传入 ChainMap 的字典含有相同的键,则对应的值为先传入的字典中的值。
此外,如果你只想单纯地迭代字典的键值对,可以结合使用 items()
和 itertools.chain()
方法:
> from itertools import chain > for k, v in chain(d1.items(), d2.items()): print(k, v) a 1 c 3 b 2 e 6 c 4 d 5
这里相同的键会被分别迭代出来。
五、保持字典有序
问题
想让字典中元素的迭代顺序和其加入字典的顺序保持一致
解决方案
通常来说,使用 d.items()
或者 d.keys()
、d.values()
方法迭代出来的元素顺序是无法预料的。例如对字典 d = {'a':1, 'b':2, 'c':3}
迭代:
> d = dict() > d['a'] = 1 > d['b'] = 2 > d['c'] = 3 > for k, v in d.items(): print(k, v) a 1 c 3 b 2
每一次运行结果都可能不同。如果想让元素迭代的顺序和创建字典时元素的顺序一致,就要使用 collections.OrderedDict
代替普通的 dict :
> from collections import OrderedDict > ordered_d = OrderedDict() > ordered_d['a'] = 1 > ordered_d['b'] = 2 > ordered_d['c'] = 3 > for k, v in ordered_d.items(): print(k, v) a 1 b 2 c 3
OrderedDict 实际通过维护一个双向链表来记录元素添加的顺序,因此其耗费的内存大约为普通字典的两倍。所以在实际使用中需综合考虑各种因素来决定是否使用 OrderedDict 。
六、使字典的键映射多个值
问题
通常情况下字典的键只对应一个值。现在想让一个键对应多个值。
解决方案
为了使一个键对应多个值,首先需要把多个值放到一个容器中(例如列表或者集合等)。例如有这样一个列表: [('a', 1), ('a', 2), ('b', 3), ('b', 4), ('c', 5)]
,我们要将其转换成一个字典,保持元素的键值对应关系,通常我们会写这样的代码:
> from pprint import pprint > l = [('a', 1), ('a', 2), ('b', 3), ('b', 4), ('c', 5)] > d = {} > for k, v in l: if k in d: d[k].append(v) else: d[k] = [v] > pprint(d) {'a': [1, 2], 'b': [3, 4], 'c': [5]}
但是 if else
语句让代码显得有点冗余和不易读,Python 的 defaultdict 改善上述代码。
> from collections import defaultdict > d = defaultdict(list) > for k, v in l: d[k].append(v) > pprint(d) defaultdict(<class 'list'>, {'c': [5], 'b': [3, 4], 'a': [1, 2]})
if else
的判语句没有了。
defaultdict 是 dict 的一个子类。对 dict 来说,如果 key 不存在,则 dict[key] 取值操作会抛出 KeyError 异常,但是 defaultdict 则会返回一个传入 defaultdict 构造器的类的实例(例如一个列表)或者自定义的缺失值。因此在上例中,对于 d[k].append(v)
,当 k 不存在时,则会先执行 d[k] = [] 并返回这个空列表,继而将 v 加入到列表中。
传入 defualtdict 构造器的值不一定要是一个类,也可以是一个可调用的函数,当相应的键不在 defualtdict 中时,其默认的值就为这个函数的返回值,例如:
> from collections import defaultdict > def zero_default(): return 0 > d = defaultdict(zero_default) > d['a'] = 1 > d['a'] 1 > d['b'] 0 > d.keys() dict_keys(['b', 'a']) >
利用这样一个特性,我们可以构造无限深度的字典结构:
> from collections import defaultdict > import json > tree = lambda: defaultdict(tree) > d = tree() > d['a']['b'] = 1 > print(json.dumps(d)) # 为了显示的格式更好看 {"a": {"b": 1}}
这里当执行 d['a'] 时,由于相应的键不存在,故返回一个 defaultdict(tree)
,当再执行 d['a']['b'] = 1
时,将键 b 对应的值设为 1 。
总结
以上就是这篇文中的全部内容,希望本文的内容对大家学习或者使用python能有一定的帮助,如果有疑问大家可以留言交流。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新动态
- 陈柏宇.2011-QUINQUENNIUM【SONY】【WAV+CUE】
- 《51首热门当红歌曲 十大顶级发烧女声 3CD》[WAV+CUE][1.6GB]
- 《赵传 深受摇滚迷青睐的台湾音乐人 约定》[WAV+CUE][320MB]
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- [音展纪念碟]2006年《TAA台湾第十六届国际HI-ENDHI-FI音响展》2cd[WAV]
- 中国音乐地图之听见西藏山歌牧歌酒歌2020[WAV分轨]
- 王宏伟2017-永远的红飘带[太平洋影音][WAV+CUE]
- 费翔.1997-NOW现在【第一中国】【WAV+CUE】
- 新格合唱团.1981-我唱你和2辑(滚石新格民歌系列)【新格】【WAV+CUE】
- 陈柏宇.2011-QUINQUENNIUM【SONY】【WAV+CUE】
- 雨果唱片-《金唛系列-蔷薇依韵琼瑶》WAV
- 陈百强《凝望(2012华纳LPCD45限量版)[DMI]》[WAV整轨]
- 模拟之声慢刻CD《徐小凤45周年》[德国母带][低速原抓WAV+CUE]
- 《庄心妍 实力唱将 发烧音乐精选集》[WAV+CUE][380MB]
- 《王菲 单曲合集》[FlAC/分轨][520MB]