Python进阶篇之字典操作总结


Posted in Python onNovember 16, 2016

一、与字典值有关的计算

问题

想对字典的值进行相关计算,例如找出字典里对应值最大(最小)的项。

解决方案一:

假设要从字典 {'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能有一定的帮助,如果有疑问大家可以留言交流。

Python 相关文章推荐
python备份文件以及mysql数据库的脚本代码
Jun 10 Python
深入讲解Python中的迭代器和生成器
Oct 26 Python
理解生产者消费者模型及在Python编程中的运用实例
Jun 26 Python
Python正则表达式如何进行字符串替换实例
Dec 28 Python
利用Tkinter(python3.6)实现一个简单计算器
Dec 21 Python
Python生成短uuid的方法实例详解
May 29 Python
python抓取需要扫微信登陆页面
Apr 29 Python
介绍一款python类型检查工具pyright(推荐)
Jul 03 Python
python3获取控制台输入的数据的具体实例
Aug 16 Python
Python实现敏感词过滤的4种方法
Sep 12 Python
python 逆向爬虫正确调用 JAR 加密逻辑
Jan 12 Python
如何用Python搭建gRPC服务
Jun 30 Python
Python极简代码实现杨辉三角示例代码
Nov 15 #Python
Python实现将不规范的英文名字首字母大写
Nov 15 #Python
利用Python开发实现简单的记事本
Nov 15 #Python
Python解析excel文件存入sqlite数据库的方法
Nov 15 #Python
听歌识曲--用python实现一个音乐检索器的功能
Nov 15 #Python
Python字典简介以及用法详解
Nov 15 #Python
python xml解析实例详解
Nov 14 #Python
You might like
php获取网页内容方法总结
2008/12/04 PHP
php分页思路以及在ZF中的使用
2012/05/30 PHP
PHP关于htmlspecialchars、strip_tags、addslashes的解释
2014/07/04 PHP
PHP动态输出JavaScript代码实例
2015/02/12 PHP
Yii2创建控制器(createController)方法详解
2016/07/23 PHP
javascript full screen 全屏显示页面元素的方法
2013/09/27 Javascript
javascript写的异步加载js文件函数(支持数组传参)
2014/06/07 Javascript
JavaScript模拟实现继承的方法
2015/03/30 Javascript
js实现简单选项卡与自动切换效果的方法
2015/04/10 Javascript
简介JavaScript中toUpperCase()方法的使用
2015/06/06 Javascript
js实现简洁大方的二级下拉菜单效果代码
2015/09/01 Javascript
4种JavaScript实现简单tab选项卡切换的方法
2016/01/06 Javascript
JavaScript数据结构学习之数组、栈与队列
2017/05/02 Javascript
vue input输入框模糊查询的示例代码
2018/05/22 Javascript
layui获取多选框中的值方法
2018/08/15 Javascript
element el-input directive数字进行控制
2018/10/11 Javascript
javascript实现计算指定范围内的质数示例
2018/12/29 Javascript
详解用JS添加和删除class类名
2019/03/25 Javascript
浅谈Node 异步IO和事件循环
2019/05/05 Javascript
bootstrap table.js动态填充单元格数据的多种方法
2019/07/18 Javascript
vue-dplayer 视频播放器实例代码
2019/11/08 Javascript
javascript设计模式 ? 享元模式原理与用法实例分析
2020/04/15 Javascript
在HTML中使用JavaScript的两种方法
2020/12/24 Javascript
[03:48]DOTA2完美大师赛主赛事第二日精彩集锦
2017/11/24 DOTA
[01:20]PWL开团时刻DAY9——听说潮汐没用?
2020/11/10 DOTA
全面解析Python的While循环语句的使用方法
2015/10/13 Python
python 字典中文key处理,读取,比较方法
2018/07/06 Python
python实现简单http服务器功能
2018/09/17 Python
三年大学生活自我鉴定
2014/01/21 职场文书
本科毕业生求职自荐信
2014/04/09 职场文书
租房安全协议书
2014/08/20 职场文书
出租房屋协议书
2014/09/14 职场文书
戒毒悔改检讨书
2014/09/21 职场文书
综合办公室岗位职责
2015/04/11 职场文书
2016年优秀党员教师先进事迹材料
2016/02/29 职场文书
浅谈node.js中间件有哪些类型
2021/04/29 Javascript