Take the 2-minute tour ×

The problem:

>>> a = dict(a=1,b=2    )
>>> b = dict(    b=3,c=2)

>>> c = ???

c = {'a': 1, 'b': 5, 'c': 2}

So, the idea is two add to dictionaries by int/float values in the shortest form. Here's one solution that I've devised, but I don't like it, cause it's long:

c = dict([(i,a.get(i,0) + b.get(i,0)) for i in set(a.keys()+b.keys())])

I think there must be a shorter/concise solution (maybe something to do with reduce and operator module? itertools?)... Any ideas?

Update: I'm really hoping to find something more elegant like "reduce(operator.add, key = itemgetter(0), a+b)". (Obviously that isn't real code, but you should get the idea). But it seems that may be a dream.

Update: Still loking for more concise solutions. Maybe groupby can help? The solution I've come up with using "reduce"/"groupby" isn't actually concise:

from itertools import groupby
from operator import itemgetter,add

c = dict( [(i,reduce(add,map(itemgetter(1), v))) \
              for i,v in groupby(sorted(a.items()+b.items()), itemgetter(0))] )
share|improve this question
long? do you have a limited number of characters or something? –  SilentGhost May 18 '09 at 11:44
Of course not, but I think there must be something more elegant, concise. It's pretty common problem (at least in my experience), and I don't think this is the shortest solution. –  Slava V May 18 '09 at 11:49
Not a big deal, but the use of (a,b,c) as both the dict names and the key names is confusing! –  Andrew Jaffe May 18 '09 at 15:07
Could you change the title of the question. It is not very meaningful. –  odwl May 18 '09 at 17:11

8 Answers 8

I think one line of code is already pretty short :)

I may become "half a line", it you use defaultdict and remove some unnecessary list and set creations:

from collections import defaultdict

a = defaultdict(int, a=1, b=2)
b = defaultdict(int, b=3, c=4)

c = dict((k, a[k]+b[k]) for k in (a.keys() + b.keys()))
print c
share|improve this answer

In my first impression, I will write:

>>> c = a.copy()
>>> for k in b: c[k] = c.get(k, 0) + b[k]
share|improve this answer

If you want short code, you're there.

If you want clean code, inherit from Ber's defaultdict and overload __add__:

from collections import defaultdict

class summable(defaultdict):
    def __add__(self, rhs):
        new = summable()
        for i in (self.keys() + rhs.keys()):
            new[i] = self.get(i, 0) + rhs.get(i, 0)
        return new

a = summable(int, a=1, b=2)
b = summable(int, b=3, c=4)
c = a + b
print c


defaultdict(None, {'a': 1, 'c': 4, 'b': 5})
share|improve this answer
self.keys() is unnecessary here. –  J.F. Sebastian Jun 22 '09 at 4:00
@J.F., I think it is necessary, but thanks for raising the issue -- my original code snip was flat wrong. Fixed and tested. –  John Pirie Jun 22 '09 at 12:56
@John Pirie: I've posted variant without self.keys() stackoverflow.com/questions/877295/python-dict-addbyvaluedict2/… –  J.F. Sebastian Jun 22 '09 at 13:38

solving not in terms of "length" but performance, I'd do the following:

>>> from collections import defaultdict
>>> def d_sum(a, b):
        d = defaultdict(int, a)
        for k, v in b.items():
            d[k] += v
        return dict(d)
>>> b = {'c': 2, 'b': 3}
>>> d_sum(a, b)
{'a': 1, 'c': 2, 'b': 5}

it's also py3k-compatible, unlike your original code.

share|improve this answer
Hmm, that's news for me. What did they change in Py3k that makes my code incompatible? –  Slava V May 18 '09 at 16:02
a.keys() + b.keys() - you would need to first convert each of them to lists for you code to work –  SilentGhost May 18 '09 at 16:51
>>> type(dict().keys()) == <type 'list'>; Isn't dict's keys() the list? –  Slava V May 19 '09 at 7:11
not in py3k: it's just a dict view, as are .values() and .items() –  SilentGhost May 19 '09 at 9:13
def GenerateSum():
  for k in set(a).union(b):
    yield k, a.get(k, 0) + b.get(k, 0)

e = dict(GenerateSum())
print e

or, with a one liner:

 print dict((k, a.get(k,0) + b.get(k,0)) for k in set(a).union(b))
share|improve this answer

The first thing I think of is a bit more efficient and (IMO) a bit more elegant, but still too much typing. Actually, it's about equivalent to kcwu's.

c = reduce(lambda(d, k): [d.update({k: d.get(k, 0) + b[k]}), d][1], b, a.copy())

It's really a shame that dict.update doesn't return self. I guess it's not the Python way. If it did, the [..., d][1] trick would be unnecessary.


%a = (a => 1, b => 2);
%b = (b => 3, c => 2);

%c = (%a, map {$_ => $a{$_} + $b{$_}} keys %b);

Haskell: "Easy things are hard, hard things are easy" "Hard things are easy, the impossible just happened"

import qualified Data.Map as M

a = M.fromList [('a', 1), ('b', 2)]
b = M.fromList [('b', 3), ('c', 2)]

c = M.unionWith (+) a b
share|improve this answer

Comment for @John Pirie's answer:

Here's implementation that doesn't use (self.keys() + rhs.keys()):

from collections import defaultdict

class sumdict(defaultdict):
    def __add__(self, rhs):
        d = self.copy() 
        d += rhs
        return d
    __radd__ = lambda self, lhs: self + lhs
    def __iadd__(self, rhs):
        for k, v in rhs.items():
            self[k] += v
        return self

a = sumdict(int, a=1, b=2)
b = dict(b=3, c=4)
c = b + a
a += b

assert a == c == {'a': 1, 'c': 4, 'b': 5} != b
share|improve this answer
Thanks for posting that -- I obviously have a lot more Python to learn. –  John Pirie Jun 23 '09 at 20:11

Easiest to just use a Counter

>>> from collections import Counter
>>> Counter(a)+Counter(b)
Counter({'b': 5, 'c': 2, 'a': 1})
>>> dict(Counter({'b': 5, 'c': 2, 'a': 1}))
share|improve this answer
+1 Simple and elegant. –  Sagar Hatekar Sep 23 '13 at 19:05

Your Answer


