15

I have a python dictionary dict1 with more than 20,000 keys and I want to update it with another dictionary dict2. The dictionaries look like this:

dict1
  key11=>[value11]
  key12=>[value12]
  ...
  ...
  keyxyz=>[value1x]      //common key
  ...... so on

dict2
  key21=>[value21]
  key22=>[value22]
  ...
  ...
  keyxyz=>[value2x]      // common key
  ........ so on

If I use

dict1.update(dict2)

then the keys of dict1 which are similar to keys of dict2 will have their values overwritten by values of dict2. What I want is if a key is already present in dict1 then the value of that key in dict2 should be appended to value of dict1. So

dict1.conditionalUpdate(dict2)

should result in

dict1
  key11=>[value11]
  key12=>[value12]
  key21=>[value21]
  key22=>[value22]
  ...
  ...
  keyxyz=>[value1x,value2x]

A naive method would be iterating over keys of dict2 for each key of dict1 and insert or update keys. Is there a better method? Does python support a built in data structure that supports this kind of functionality?

Bo.
  • 2,547
  • 3
  • 24
  • 36
lovesh
  • 5,235
  • 9
  • 62
  • 93

3 Answers3

14

Use defaultdict from the collections module.

>>> from collections import defaultdict
>>> dict1 = {1:'a',2:'b',3:'c'}
>>> dict2 = {1:'hello', 4:'four', 5:'five'}
>>> my_dict = defaultdict(list)
>>> for k in dict1:
...    my_dict[k].append(dict1[k])
...
>>> for k in dict2:
...    my_dict[k].append(dict2[k])
...
>>> my_dict[1]
['a', 'hello']
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
  • 1
    Correct. In fact, if you check out the Python docs there is an example which nearly matches what you're asking for - http://docs.python.org/library/collections.html#defaultdict-examples – Aaron Newton May 17 '12 at 11:56
3

Another method without importing anything, just with the regular Python dictionary:

>>> dict1 = {1:'a',2:'b',3:'c'}
>>> dict2 = {1:'hello', 4:'four', 5:'five'}
>>> for k in dict2:
...  dict1[k] = dict1.get(k,"") + dict2.get(k)
... 
>>> dict1
{1: 'ahello', 2: 'b', 3: 'c', 4: 'four', 5: 'five'}
>>> 

dict1.get(k,"") returns the value associated to k if it exists or an empty string otherwise, and then append the content of dict2.

Julien-L
  • 5,267
  • 3
  • 34
  • 51
1

This is actually pretty simple to do using a dict comprehension and itertools.groupby():

dict1 = {1: 1, 2: 2, 3: 3, 4: 4}
dict2 = {5: 6, 7: 8, 1: 1, 2: 2}

from itertools import groupby, chain
from operator import itemgetter

sorted_items = sorted(chain(dict1.items(), dict2.items()))

print({key: [value[1] for value in values] for key, values in groupby(sorted_items, itemgetter(0))})

Gives us:

{1: [1, 1], 2: [2, 2], 3: [3], 4: [4], 5: [6], 7: [8]}

Naturally, this creates a new dict, but if you need to update the first dict, you can do that trivially by updating with the new one. If your values are already lists, this may need some minor modification (but I presume you were doing that for the sake of the operation, in which case, there is no need).

Naturally, if you are using Python 2.x, then you will want to use dict.viewitems() or dict.iteritems() over dict.items(). If you are using a version of Python prior to dict comprehensions, then you could use dict((key , value) for ...) instead.

Gareth Latty
  • 86,389
  • 17
  • 178
  • 183