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:
d1 = {'a': 1, 'b': 2}
d2 = {'b': 3, 'c': 4}
{'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:
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():
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¶
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.
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.
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.