I have two dictionaries, and what I'm trying to do is a bit odd. Basically, I want to merge them. That's simple enough. But they're hierarchies of of dictionaries, and I want to merge them in such a way that if an item in a dictionary is itself a dictionary and exists in both, I want to merge those dictionaries as well. If it's not a dictionary, I want the values from the second dictionary to overwrite the values from the first one. Something sort of like this:
a = {0: {0: "a"},
1: [0, 1, 2]}
b = {0: {1: "b"},
1: [3, 4, 5]}
Merge(a, b)
#output:
{0: {0: "a",
1: "b"},
1: [3, 4, 5]}
Does that make sense? Because the key "0" contained a dictionary in both a and b, it merged those dictionaries as well. But in the case of the second key, it was a list so it just overwrote it.
So I suppose I'll be looking at some kind of recursive function? Not quite sure how to approach this one.
Thanks!
Edit: I forgot to mention one pretty crucial detail:
I need a function that works in both 2.6.2 and 2.7.3.
解决方案
Assuming you might have nested dictionaries (based on your thinking in terms of recursion), something like this should work,
from copy import deepcopy
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = a.viewkeys() & b.viewkeys()
every_key = a.viewkeys() | b.viewkeys()
return {k: merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k]) for k in every_key}
return deepcopy(b)
The return value of merge(a, b) is conceptually like creating a (deep) copy of a and running a recursive version of a.update(b).
Using some nested examples,
a = {0: {0: 'a'},
1: [0, 1, 2],
2: [9, 9],
3: {'a': {1: 1, 2: 2}, 'b': [0, 1]}}
b = {0: {1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {2: 22, 3: 33}, 'b': [99, 88]}}
merge(a, b) produces,
{0: {0: 'a', 1: 'b'},
1: [3, 4, 5],
2: {22: 22, 33: 33},
3: {'a': {1: 1, 2: 22, 3: 33}, 'b': [99, 88]}}
EDIT: Python 2.6 version
def merge(a, b):
if isinstance(b, dict) and isinstance(a, dict):
a_and_b = set(a).intersection(b)
every_key = set(a).union(b)
return dict((k, merge(a[k], b[k]) if k in a_and_b else
deepcopy(a[k] if k in a else b[k])) for k in every_key)
return deepcopy(b)