博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
字典对象相加
阅读量:5982 次
发布时间:2019-06-20

本文共 2294 字,大约阅读时间需要 7 分钟。

SO上看到一个比较好的问题.大概是:

For example I have two dicts:

Dict A:{
'a':1,'b':2,'c':3} Dict B:{
'b':3,'c':4,'d':5}

I need a pythonic way of 'combining' two dicts such that the result is :

{
'a':1,'b':5,'c':7,'d':5}

That is to say: if a key appears in both dicts, add their values, if it appears in only one dict, keep its value.

 

我发现有3类答案,每一个都有值得学习的地方.

(1)首先来一个比较酷的解法:

a = {
'a': 'foo', 'b':'bar', 'c': 'baz'}b = {
'a': 'spam', 'c':'ham', 'x': 'blah'}r = dict(a.items() + b.items() + [(k, a[k] + b[k]) for k in set(b) & set(a)])

这里面用到了一个难以觉察到的设置,举例说明:

>>> dict([(1,2),(1,2),(1,3),(2,3),(2,4)]){
1: 3, 2: 4}

可以看到,在将列表转换为字典的过程中,如果出现了相同的键,那么Python是默认取最后一个键及其对应的值.

另外,set的用法也显得非常简练.作者后来还给出了更普遍的版本:

def combine_dicts(a, b, op=None):    op = op or (lambda x, y: x + y)    return dict(a.items() + b.items() +        [(k, op(a[k], b[k])) for k in set(b) & set(a)])

我才知道OR运算符不是仅仅返回True或False的...

>>> a= None or 2>>> a2>>> 4 or 24>>> not None or 2True>>>

这位作者曾经解答过我一个遍历树的问题,我花了一天时间冥思苦想,最后在递归和生成器的理解上进步一大截.

这是他SO主页:

 

(2)下面来一个面向对象风格的:

class MyDict(dict):    def __add__(self, oth):        r = self.copy()        for key, val in oth.items():            if key in r:                r[key] += val # You can custom it here            else:                r[key] = val        return ra = MyDict({
'a':1, 'b':2, 'c':3})b = MyDict({
'b':3, 'c':4, 'd':5})print a+b # Output {'a':1, 'b': 5, 'c': 7, 'd': 5}

原来__add__方法是这么来的.同时我也觉得,面向对象编程还是挺不错的,继承,撰写特殊方法,很方便的嘛.

另外,字典的copy方法原来就是在这种地方起作用的--很方便地返回一个和原字典内容一样的新的字典对象.毕竟2个字典相加后返回的新字典一般都是要求具有独立性的.

以前我一直想不通这个方法是拿来干嘛的..现在是明白一些了.

 

题外话:出于对copy一贯的警觉,我对字典的copy方法进行了一些测试,发现还是一贯地"陷阱".并非那么独立..

>>> d={1: [], 2: 4}>>> e=d.copy()>>> e{
1: [], 2: 4}>>> e[1].append('trap?')>>> d{
1: ['trap?'], 2: 4}

可见,当字典的值是可变对象时(比如list),copy是返回一个引用,并非新对象.总之,如果你的字典值包含可变对象,为了确保不发生"惊喜",还是用copy.deepcopy吧:

>>> import copy>>> e=copy.deepcopy(d)>>> e{
1: ['trap?'], 2: 4}>>> e[1].append('no_trap')>>> d{
1: ['trap?'], 2: 4}>>>

 

(3)最后是典型的Python风格--找现成轮子,import搞定之:

>>> from collections import Counter>>> A = Counter({
'a':1, 'b':2, 'c':3})>>> B = Counter({
'b':3, 'c':4, 'd':5})>>> A + BCounter({
'c': 7, 'b': 5, 'd': 5, 'a': 1})

 

目前发现Python有以下一些基础库,提供一些不牵扯具体应用的有用的函数:

collections functools operator itertools

 

 

转载于:https://www.cnblogs.com/xiangnan/p/3393153.html

你可能感兴趣的文章
phpstorm xdebug remote配置
查看>>
引用与指针的区别
查看>>
pygtk笔记--2.1:布局容器,VBox、Hbox、Alignment
查看>>
dtree.js树的使用
查看>>
Springboot2.1.3 + redis 实现 cache序列化乱码问题
查看>>
线程什么时候需要同步,什么时候不需要同步?
查看>>
Struts2 自定义拦截器(方法拦截器)
查看>>
Linux服务器的那些性能参数指标
查看>>
BZOJ 2302: [HAOI2011]Problem c [DP 组合计数]
查看>>
c++ 11开始语言本身和标准库支持并发编程
查看>>
.NET Core 之 MSBuild 介绍
查看>>
iOS:即时通讯之<了解篇 SocKet>
查看>>
《JavaScript高级程序设计》读书笔记(十):本地对象Date
查看>>
linux中fork()函数详解
查看>>
从1G到5G,46年屏幕变迁下,富士康、苹果、三星、华为的浴火重生路 ...
查看>>
用flash测试你的ircd
查看>>
白话红黑树系列之二——红黑树的构建
查看>>
客户的一张表中出现重复数据,而该列由唯一键约束,重复值如何产生的呢?...
查看>>
MySQL5.6中新增特性、不推荐使用的功能以及废弃的功能
查看>>
OnePlus安装Kali-NetHunter
查看>>