outon
outon

Reputation: 116

How to merge two dicts and combine common keys?

I would like to know how if there exists any python function to merge two dictionary and combine all values that have a common key.

I have found function to append two dict, to merge two dict but not to combine its values.

Example:

D1 = [{k1: v01},            {k3: v03}, {k4: v04},}],
D2 = [{k1: v11}, {k2: v12},            {k4: v14},}],

this should be the expected result:

D3 = [
   {k1: [v01, v11]},
   {k2: [     v12]},
   {K3: [v03     ]},
   {k4: [v04, v14]},
 ]

Upvotes: 1

Views: 3223

Answers (4)

srj
srj

Reputation: 10111

A more generic way to merge dicts together may look like this. (To answer a similar SO question)

def merge(combiner, dicts):
    new_dict = {}
    for d in dicts:
       for k, v in d.items():
           if k in new_dict:
               new_dict[k] = combiner(new_dict[k], v)
           else:
               new_dict[k] = v
    return new_dict

x = {'a': 'A', 'b': 'B'}
y = {'b': 'B', 'c': 'C'}
z = {'a': 'A', 'd': 'D'}
merge_dicts(combiner= lambda x, y: f'{x} AND {y}', dicts=(x,y,z))
# {'a': 'A AND A', 'b': 'B AND B', 'c': 'C', 'd': 'D'}

Upvotes: 0

gilch
gilch

Reputation: 11651

If you meant to use actual dicts, instead of lists of dicts, this is easier.

D1 = dict(k1=1, k3=3, k4=4)
D2 = dict(k1=11, k2=12, k4=14)

There isn't a simple built-in function to do this, but the setdefault method is close. It tries to get the given key, but creates it if it doesn't exist.

D3 = {}
for k, v in D1.items() | D2.items():
    D3.setdefault(k, set()).add(v)

And the result.

{'k4': {4, 14}, 'k1': {1, 11}, 'k3': {3}, 'k2': {12}}

This all assumes the order doesn't matter, just combining sets.

Upvotes: 1

Yaakov Bressler
Yaakov Bressler

Reputation: 12018

A solution, without importing anything:

# First initialize data, done correctly here.
D1 = [{'k1': 'v01'},            {'k3': 'v03'}, {'k4': 'v04'}]
D2 = [{'k1': 'v11'}, {'k2': 'v12'},            {'k4': 'v14'}]

# Get all unique keys
keys = {k for d in [*D1, *D2] for k in d}

# Initialize an empty dict
D3 = {x:[] for x in keys}

# sort to maintain order
D3 = dict(sorted(D3.items()))

#Iterate and extend
for x in [*D1, *D2]:
    for k,v in x.items():
        D3[k].append(v)

# NOTE: I do not recommend you convert a dictionary into a list of records.
# Nonetheless, here is how it would be done.
# To convert to a list
D3_list = [{k:v} for k,v in D3.items()]

print(D3_list)

# [{'k1': ['v01', 'v11']},
#  {'k2': ['v12']},
#  {'k3': ['v03']},
#  {'k4': ['v04', 'v14']}]

Upvotes: 1

Thibault D.
Thibault D.

Reputation: 1637

There is no built-in function for this but you can use a defaultdict for this:

from collections import defaultdict
d = defaultdict(list)
for other in [d1, d1]:
    for k, v in other.items():
        d[k].append(v)

Upvotes: 3

Related Questions