Skip to content

S2Q1 · Merge Two Dictionaries and Sum on Conflicts

⚡ Quick Reference

Function: merge_dictionaries(d1: dict, d2: dict) -> dict

Core idea: start with a copy of d1, then for each key in d2 either add to existing value or insert new key.

def merge_dictionaries(d1: dict, d2: dict) -> dict:
    result = dict(d1)
    for key, value in d2.items():
        result[key] = result.get(key, 0) + value
    return result

Key rules: - If key exists in both → sum the values - If key exists in only one → include as-is - Returns a new dict - does not modify d1 or d2 - dict.get(key, 0) returns 0 if key is absent - avoids a KeyError


Problem Statement

Problem

Write a function merge_dictionaries(d1, d2) that merges two dictionaries. For keys present in both, sum their values. For keys in only one, include as-is.

Example:

Input
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
Output
{'a': 1, 'b': 5, 'c': 4}

Understanding the problem

Three categories of keys to handle:

Key Present in Action
'a' d1 only Include as-is: 1
'b' both d1 and d2 Sum values: 2 + 3 = 5
'c' d2 only Include as-is: 4

dict.get(key, 0)

result.get(key, 0) returns the current value for key if it exists, or 0 if it doesn't. This lets us handle both the "key already exists" and "key is new" cases in one expression:

result[key] = result.get(key, 0) + value
# If key exists:   current_value + value  (sum)
# If key is new:   0 + value              (insert as-is)

Tracing the example

d1 = {'a': 1, 'b': 2}, d2 = {'b': 3, 'c': 4}

Start: result = {'a': 1, 'b': 2}   (copy of d1)

Process d2:
  key='b', value=3:
    result.get('b', 0) = 2
    result['b'] = 2 + 3 = 5
    result = {'a': 1, 'b': 5}

  key='c', value=4:
    result.get('c', 0) = 0   (not present)
    result['c'] = 0 + 4 = 4
    result = {'a': 1, 'b': 5, 'c': 4}

Return: {'a': 1, 'b': 5, 'c': 4} 

Solution approaches

def merge_dictionaries(d1: dict, d2: dict) -> dict:
    result = dict(d1)
    for key, value in d2.items():
        result[key] = result.get(key, 0) + value
    return result
def merge_dictionaries(d1: dict, d2: dict) -> dict:
    result = dict(d1)
    for key, value in d2.items():
        if key in result:
            result[key] = result[key] + value   # sum on conflict
        else:
            result[key] = value                 # insert new key
    return result

Explicit branching - the two cases are clearly separated.

from collections import Counter

def merge_dictionaries(d1: dict, d2: dict) -> dict:
    return dict(Counter(d1) + Counter(d2))

Counter supports + to sum values of matching keys. Elegant for integer values - note that Counter drops keys with zero or negative values after addition, so use with care for non-positive numbers.

def merge_dictionaries(d1: dict, d2: dict) -> dict:
    all_keys = d1.keys() | d2.keys()
    return {k: d1.get(k, 0) + d2.get(k, 0) for k in all_keys}

d1.keys() | d2.keys() gives the union of all keys. For each key, sum contributions from both dicts (defaulting to 0 if absent). Clean and symmetric - treats both dicts equally.

def merge_dictionaries(d1: dict, d2: dict) -> dict:
    all_keys = d1.keys() | d2.keys()
    return dict(map(
        lambda k: (k, d1.get(k, 0) + d2.get(k, 0)),
        all_keys
    ))

map(lambda k: (k, ...), all_keys) transforms each key into a (key, summed_value) tuple. dict() converts the list of tuples into the final dictionary. A functional alternative to the comprehension approach - same logic, different style.


Key takeaways

01

dict.get(key, default)

Returns the value for key if present, otherwise default. Use get(key, 0) to safely handle missing keys in numeric accumulation without a KeyError.

02

Copy before modifying

result = dict(d1) creates a shallow copy. Always work on a copy when you need to return a new dict without modifying the originals.

03

Key union: d1.keys() | d2.keys()

Dict key views support set operations. | gives the union, & gives the intersection, - gives the difference. Useful for working across multiple dicts.