Skip to content

Instantly share code, notes, and snippets.

@huyx
Last active August 29, 2015 14:03
Show Gist options
  • Save huyx/984c3340f332366d8a29 to your computer and use it in GitHub Desktop.
Save huyx/984c3340f332366d8a29 to your computer and use it in GitHub Desktop.
Merge dict or dict like object,, include OrderedDict。
# -*- coding: utf-8 -*-
u'''合并字典,可用于配置信息合并
合并的原则是后来的数据优先
'''
def mergeable(target, source):
'''
>>> from collections import OrderedDict
>>> mergeable({}, {})
True
>>> mergeable(OrderedDict(), {})
True
>>> mergeable({}, OrderedDict())
True
>>> mergeable('target', {})
False
>>> mergeable([], {})
False
>>> mergeable({}, 'source')
False
>>> mergeable({}, [])
False
'''
if isinstance(target, (basestring, tuple, list)):
return False
if isinstance(source, (basestring, tuple, list)):
return False
if isinstance(target, dict) and isinstance(source, dict):
return True
return all((
hasattr(target, 'keys'),
hasattr(target, '__getitem__'),
hasattr(target, '__setitem__'),
hasattr(source, 'keys'),
hasattr(target, '__getitem__'),
))
def merge_dict(target, source):
'''
>>> from collections import OrderedDict
>>> merge_dict(OrderedDict(), OrderedDict([('a', 1)]))
OrderedDict([('a', 1)])
>>> merge_dict(OrderedDict([('a', 1)]), OrderedDict([('a', 2)]))
OrderedDict([('a', 2)])
>>> merge_dict(OrderedDict([('a', 1)]), OrderedDict([('b', 2)]))
OrderedDict([('a', 1), ('b', 2)])
'''
assert mergeable(target, source)
targetKeys = target.keys()
sourceKeys = source.keys()
for key in sourceKeys:
source_value = source[key]
if key in targetKeys:
target_value = target[key]
if mergeable(target_value, source_value):
merge_dict(target_value, source_value)
else:
target[key] = source_value
else:
target[key] = source_value
return target
if __name__ == '__main__':
import doctest
doctest.testmod()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment