-1

I have two or more dictionary, I like to merge it as one with retaining multiple values of the same key as list. I would not able to share the original code, so please help me with the following example.

Input:

a= {'a':1, 'b': 2}
b= {'aa':4, 'b': 6}
c= {'aa':3, 'c': 8}

Output:

c= {'a':1,'aa':[3,4],'b': [2,6], 'c': 8}

3 Answers3

1

I suggest you read up on the defaultdict: it lets you provide a factory method that initializes missing keys, i.e. if a key is looked up but not found, it creates a value by calling factory_method(missing_key). See this example, it might make things clearer:

from collections import defaultdict

a = {'a': 1, 'b': 2}
b = {'aa': 4, 'b': 6}
c = {'aa': 3, 'c': 8}

stuff = [a, b, c]
# our factory method is the list-constructor `list`,
# so whenever we look up a value that doesn't exist, a list is created;
# we can always be sure that we have list-values
store = defaultdict(list)

for s in stuff:
    for k, v in s.items():
        # since we know that our value is always a list, we can safely append
        store[k].append(v)

print(store)

This has the "downside" of creating one-element lists for single occurences of values, but maybe you are able to work around that.

Oliver Baumann
  • 2,209
  • 1
  • 10
  • 26
  • 1
    The downside is, in fact, an upside. Given future logic will no longer have to differentiate between scalars and one-element lists. Consistency is best. – jpp Oct 18 '18 at 10:57
0

Please find below to resolve your issue. I hope this would work for you.

from collections import defaultdict

a = {'a':1, 'b': 2}
b =  {'aa':4, 'b': 6}
c={'aa':3, 'c': 8}

dd = defaultdict(list)

for d in (a,b,c): 
    for key, value in d.items():
        dd[key].append(value)

print(dd)
Parul Garg
  • 102
  • 1
  • 10
0

Use defaultdict to automatically create a dictionary entry with an empty list.

To process all source dictionaries in a single loop, use itertools.chain.

The main loop just adds a value from the current item, to the list under the current key.

As you wrote, for cases when under some key there is only one item, you have to generate a work dictionary (using dictonary comprehension), limited to items with value (list) containing only one item. The value of such item shoud contain only the first (and only) number from the source list.

Then use this dictionary to update d.

So the whole script can be surprisingly short, as below:

from collections import defaultdict
from itertools import chain
a = {'a':1, 'b': 2}
b = {'aa':4, 'b': 6}
c = {'aa':3, 'c': 8}
d = defaultdict(list)
for k, v in chain(a.items(), b.items(), c.items()):
    d[k].append(v)
d.update({ k: v[0] for k, v in d.items() if len(v) == 1 })

As you can see, the actual processing code is contained in only 4 (last) lines.

If you print d, the result is:

defaultdict(list, {'a': 1, 'b': [2, 6], 'aa': [4, 3], 'c': 8})
Valdi_Bo
  • 30,023
  • 4
  • 23
  • 41