Skip to content

Instantly share code, notes, and snippets.

@markizano
Created April 27, 2022 16:17
Show Gist options
  • Save markizano/acdeb0d32ccae28ad583f779e5c3198f to your computer and use it in GitHub Desktop.
Save markizano/acdeb0d32ccae28ad583f779e5c3198f to your computer and use it in GitHub Desktop.
Enables one to merge dictionaries in Python whilst preserving previous keys.
def dictmerge(target, *args):
'''
Merge multiple dictionaries.
Usage:
one = {'one': 1}
two = {'two': 2}
three = {'three': 3}
sum = dictmerge(one, two, three)
{one: 1, two: 2, three: 3}
'''
target = copy.deepcopy(target)
if len(args) > 1:
for obj in args:
target = dictmerge(target, obj)
return target
obj = copy.deepcopy(args[0])
# Try to combine basic algorithms we know will work for sure.
try:
if isinstance(target, (bool, int, float, str, list, tuple, set)) and isinstance(obj, (bool, int, float, str, list, tuple, set)):
if isinstance(target, bool) and isinstance(obj, bool):
return target and obj
if isinstance(target, (int, float)) and isinstance(obj, (int, float)):
return target + obj
if isinstance(target, (list, tuple, set)) and isinstance(obj, (list, tuple, set)):
return list(target + obj)
raise ValueError('Invalid Argument')
elif isinstance(target, dict) and isinstance(obj, dict):
# Don't take action on dictionaries. We will execute on them in the following lines after the exception tracking.
pass
else:
raise ValueError('Invalid Argument')
except Exception as e:
raise ValueError('\x1b[33mCould not merge\x1b[0m %s(%s) and %s(%s); Error=%s' % (type(target), target, type(obj), obj, e) )
# Recursively merge dicts and set non-dict values
for k, v in list(obj.items()):
if k in target and isinstance(v, dict):
target[k] = dictmerge(target[k], v)
elif k in target and isinstance(v, (set, tuple, list)):
target[k] = target[k] + v
else:
target[k] = v
return target
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment