当前位置: 首页 > news >正文

Python Cookbook-4.17 字典的并集与交集

任务

给定两个字典,需要找到两个字典都包含的键(交集),或者同时属于两个字典的键(并集)。

解决方案

有时,尤其是在Python2.3中,你会发现对字典的使用完全是对集合的一种具体化的体现。在这个要求中,只需要考虑键,不用考虑键的对应值,一般可以通过调用dict.fromkeys 来创建字典,像这样:


a = dict.fromkeys(xrange(1000))
b = dict.fromkeys(xrange(500,1500))

最快计算出并集的方法是:

union = dict(a,**b)

而最快且最简洁地获得交集的方法是:

inter = dict.fromkeys([x for x in a if x in b])

如果字典a和b的条目的数目差异大,那么在for子句中用较短的那个字典,在if子句中用较长的字典会有利于提升运算速度。在这种考虑之下,牺牲简洁性以获取性能似乎是值得的,交集计算可以被改为:

if len(a) < len(b):
	inter = dict.fromkeys([x for x in a if x not in b])
else:
	inter = dict.fromkeys([x for x in b if x not in a])

Python 也提供了直接代表集合的类型(标准库中的sets模块,在 Python 2.4中已经成为了内建的部分)。可以把下面的代码片段用在模块的开头,这个代码片段确保了名字 set被绑定到了适合的类型,这样在整个模块中,无论你用 Python 2.3 还是 2.4,都可以使用同样的代码:

try:
	set
except NameError:
	from sets import Set as set

这样做的好处是,可以到处使用 set类型,同时还获得了清晰和简洁,以及速度的提升(在Python2.4中):

a = set(xrange(1000))
b = set(xrange(500,1500))
union = a|b
inter = a&b

讨论

虽然 Python 2.3的标准库模块 sets 已经提供了一个优雅的数据类型 set来代表集合(带有可哈希(hashable)的元素),但由于历史原因,使用 dict 来代表集合仍然是很普遍的。基于这个目的,本节展示了如何用最快的方法来计算这种集合的交集和并集。本节的代码在我的计算机上,并集计算耗时260us,交集计算则耗时690us(Python 2.3;260ms和 600s),而其他的基于循环或者生成器在Python2.4中,这两个数字分别是表达式的方法会更慢。

不过,最好还是用 set类型而不是字典来代表集合。如同本节所示,使用set能让代码更加直接和易读。如果你不喜欢或操作符()和与操作符(&),可以使用等价的a.union(b)和a.intersection(b)。这样操作除了清晰,速度也有提升,特别是在 Pyton 2.4中,计算并集需要 260us,但计算交集只需要 210us。即使是在 Python 2.3,其速度也是可以接受的:并集计算耗时 270us,交集计算耗时650us,没有在Python 2.4快,但如果你仍然用字典来代表集合的话,速度其实是相当的。最后一点,一旦你引入set类型(无论是 Python 2.4 内建的,还是通过 Python 标准库 sets 模块引入的,接口是一样的),你将获得丰富的集合操作。举个例子,属于a或者b但却不属于a和b的交集的集合是a^b,可以等价地被表示为 a.symmetric_difference(b)。

即使由于某些原因使用了 dict,也应当尽可能地用set 来完成集合操作。举个例子,假设你有个字典phones,将人名映射到电话号码,还有个字典address,将人名映射到地址。最清楚简单地打印所有同时知道地址和电话号码的人名及其相关数据的方法是:

for name in set(phones) & set(addresses):
	print name,phones[name],addresses[name]

跟下面的方法比,这非常简洁,虽然清晰度可能还有争议:

for name in phones:
	if name in addresses:
		print name,phones[name],addresses[name]

另一个很好的可选方法是:

for name in set(phones).intersection(addresses):
	print name,phones[name],addresses[name]

如果使用 intersection 方法,而不是&交集操作,就不需要将两个字典都转化成 set,只需要其中一个。然后再对转化后的set调用intersection,并传入另一个dict 作为intersection方法的参数。

相关文章:

  • 翻译: 人工智能如何让世界变得更美好一
  • 【Easylive】项目常见问题解答(自用持续更新中......)
  • 量子退火实用案例(1):量子退火求解化学中的分子吸附问题,10小时缩短为15分
  • 周总结aa
  • 多段圆弧拟合离散点实现切线连续
  • 【Vue2插槽】
  • PDF解析黑科技:从OCR-Free到多模态大模型的进化之旅
  • 43、接口请求需要时间,导致页面初始加载时会出现空白,影响用户体验
  • Python实现音频数字水印方法
  • Python人工智能大模型入门教程:从零构建高性能预测模型
  • linux文件/目录所在组/其他组
  • oracle 常用函数的应用
  • 数据结构 并查集 并查集的操作以及结构
  • 凸包构造算法—Graham 扫描法
  • 怎么把wps中的word的批注全部删掉
  • ArgoCD 可观测性最佳实践
  • 查看npm安装了哪些全局依赖
  • [electron] electron の 快速尝试
  • 应用分享 | AWG技术突破:操控钻石氮空位色心,开启量子计算新篇章!
  • Window对象的常用属性和方法
  • 做网站赚广告/关键词组合工具
  • 企业网站免费/网站在线优化工具
  • 网站建设大型/百度一下你就知道手机版
  • 大型车产品网站建设/网络营销的内容主要有哪些
  • 海外兼职网站建设/百度客服电话人工服务热线
  • 长沙模板建站哪家好/淮北seo排名