有一个简单的字典,像这样:
{"a.b": "foo", "a.c": "bar", "d.e.f":"baz"}
以及如何使用Python将dict传递到此:
{
"a":
{
"b": "foo",
"c": "bar"
},
"d":
{
"e":
{
"f": "baz"
}
}
}
答案 0 :(得分:3)
您可以使用以下方法将split
上的键.
转换为最后一个值和之前的所有内容:
*parents, key = k.split('.')
您可以使用类似以下内容来挖掘嵌套字典(如果需要,可以创建它们):
end = reduce(lambda x, y: x.setdefault(y, {}) , parents, new_d)
此处end
将是链末尾的字典。因此,此时您只需分配值即可。像这样:
from functools import reduce
d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz", "d.e.g":"M", 'l':"single_key_test" }
new_d = {}
for k in d:
*parents, key = k.split('.')
end = reduce(lambda x, y: x.setdefault(y, {}) , parents, new_d)
end[key] = d[k]
print(new_d)
结果:
{'a': {'b': 'foo', 'c': 'bar'}, 'd': {'e': {'f': 'baz', 'g': 'M'}}, 'l': 'single_key_test'}
答案 1 :(得分:1)
首先,您必须用'.'
分割密钥以获取路径。
然后,您可以创建一个从一个路径创建嵌套字典的函数:
def make_nested_dict(iterable, final):
"""Make nested dict from iterable"""
if iterable:
head, *tail = iterable
return {head: make_nested_dict(tail, final)}
else:
return final
其工作方式如下:
d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz"}
for key in d:
paths = key.split('.')
nested_path = make_nested_dict(paths, d[key])
print(nested_path)
并给出以下路径:
{'a': {'b': 'foo'}}
{'a': {'c': 'bar'}}
{'d': {'e': {'f': 'baz'}}}
然后,您可以创建一个将两个嵌套字典递归合并的函数:
def merge_nested_dicts(d1, d2):
"""Merge two nested dictionaries together"""
for key in d2:
if key in d1:
if isinstance(d2[key], dict) and isinstance(d1[key], dict):
merge_nested_dicts(d1[key], d2[key])
else:
d1[key] = d2[key]
return d1
您可以通过更新结果嵌套的dict来合并:
nested_dict = {}
for key in d:
paths = key.split('.')
nested_path = make_nested_dict(paths, d[key])
nested_dict = merge_nested_dicts(nested_dict, nested_path)
print(nested_dict)
现在,这给出了以下内容:
{'a': {'b': 'foo', 'c': 'bar'}, 'd': {'e': {'f': 'baz'}}}
完整的代码并附有评论:
def make_nested_dict(iterable, final):
"""Make nested dictionary path with a final attribute"""
# If iterable, keep recursing
if iterable:
# Unpack key and rest of dict
head, *tail = iterable
# Return new dictionary, recursing on tail value
return {head: make_nested_dict(tail, final)}
# Otherwise assign final attribute
else:
return final
def merge_nested_dicts(d1, d2):
"""Merge two nested dictionaries together"""
for key in d2:
# If we have matching keys
if key in d1:
# Only merge if both values are dictionaries
if isinstance(d2[key], dict) and isinstance(d1[key], dict):
merge_nested_dicts(d1[key], d2[key])
# Otherwise assign normally
else:
d1[key] = d2[key]
return d1
if __name__ == "__main__":
d = {"a.b": "foo", "a.c": "bar", "d.e.f":"baz", "d.e.g":"M", 'l':"single_key_test" }
nested_dict = {}
for key in d:
# Create path
paths = key.split('.')
# Create nested path
nested_path = make_nested_dict(paths, d[key])
# Update result dict by merging with new dict
nested_dict = merge_nested_dicts(nested_dict, nested_path)
print(nested_dict)