热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Python进阶篇之字典操作总结

一、与字典值有关的计算问题想对字典的值进行相关计算,例如找出字典里对应值最大(最小)的项。解决方案一:假设要从字典{a:3,b:2,c:6}中找出值最小的项,可以这样做:>>>d{a

一、与字典值有关的计算

问题

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

解决方案一:

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


推荐阅读
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • Android JSON基础,音视频开发进阶指南目录
    Array里面的对象数据是有序的,json字符串最外层是方括号的,方括号:[]解析jsonArray代码try{json字符串最外层是 ... [详细]
  • 本文介绍了Java的集合及其实现类,包括数据结构、抽象类和具体实现类的关系,详细介绍了List接口及其实现类ArrayList的基本操作和特点。文章通过提供相关参考文档和链接,帮助读者更好地理解和使用Java的集合类。 ... [详细]
  • 标题: ... [详细]
  • 本文讨论了在openwrt-17.01版本中,mt7628设备上初始化启动时eth0的mac地址总是随机生成的问题。每次随机生成的eth0的mac地址都会写到/sys/class/net/eth0/address目录下,而openwrt-17.01原版的SDK会根据随机生成的eth0的mac地址再生成eth0.1、eth0.2等,生成后的mac地址会保存在/etc/config/network下。 ... [详细]
  • 集合的遍历方式及其局限性
    本文介绍了Java中集合的遍历方式,重点介绍了for-each语句的用法和优势。同时指出了for-each语句无法引用数组或集合的索引的局限性。通过示例代码展示了for-each语句的使用方法,并提供了改写为for语句版本的方法。 ... [详细]
  • Python SQLAlchemy库的使用方法详解
    本文详细介绍了Python中使用SQLAlchemy库的方法。首先对SQLAlchemy进行了简介,包括其定义、适用的数据库类型等。然后讨论了SQLAlchemy提供的两种主要使用模式,即SQL表达式语言和ORM。针对不同的需求,给出了选择哪种模式的建议。最后,介绍了连接数据库的方法,包括创建SQLAlchemy引擎和执行SQL语句的接口。 ... [详细]
  • WhenIusepythontoapplythepymysqlmoduletoaddafieldtoatableinthemysqldatabase,itdo ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
author-avatar
秀珍冠秋晓雯
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有