Python3 字典理解与子字典打包?
Python3 dictionary comprehension with sub-dictionary upacking?
假设有一本字典,root
,它由 key:value 对组成,其中一些值本身就是字典。
能否(如果可以,如何)通过字典理解解压这些子词典?
例如
{k: v if type(v) is not dict else **v for k, v in root.items()}
示例:
root = {'a': 1, 'b': {'c': 2, 'd': 3}}
result = {'a': 1, 'c': 2, 'd': 3}
我想我应该 post 作为一个有更广泛解释的答案来帮助你,因为它与其他现有问题有点不同
{
_k: _v
for k, v in root.items()
for _k, _v in ( # here I create a dummy dictionary if non exists
v if isinstance(v, dict) else {k: v}
).items() # and iterate that
}
理解的关键部分是你需要一致和通用的逻辑才能使理解起作用。
您可以通过使用 v if isinstance(v, dict) else {k: v}
创建 dummy 以前不存在的嵌套字典来做到这一点
那么这是一个简单的嵌套字典拆包练习。
为了帮助您以后理解,我建议您写出代码,例如
res = dict()
for k,v in root.items():
d = v if isinstance(v, dict) else {k: v}
for _k, _v in d.items():
res[_k] = _v
并以此为基础倒推
有用的参考资料
- Putting a simple if-then-else statement on one line
- Nested dictionary comprehension python
如果你有多层嵌套字典,我建议你使用以下基于递归函数的解决方案:
def flatten(res, root):
for k,v in root.items():
if isinstance(v, dict):
flatten(res, v)
else:
res[k] = v
root = {'a': 1, 'b': {'c': 2, 'd': {'e': 5, 'f': 6}}}
result = {}
flatten(result, root)
print(result) # {'a': 1, 'c': 2, 'e': 5, 'f': 6}
这是一个递归的解决方案。在函数 _flatten_into_kv_pairs
中,我们遍历键和值对,如果值不是字典,则生成那些 keys/values。如果是,那么我们使用 yield from
构造递归调用 _flatten_into_kv_pairs
。函数 flatten_dict
只是一个 shell,它将 key/value 对的序列转回字典。
def _flatten_into_kv_pairs(dict_object):
for k, v in dict_object.items():
if isinstance(v, dict):
yield from _flatten_into_kv_pairs(v)
else:
yield k, v
def flatten_dict(dict_object):
return dict(_flatten_into_kv_pairs(dict_object))
root = {'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, 'g': 5}}}
print(flatten_dict(root))
输出:
{'a': 1, 'c': 2, 'd': 3, 'f': 4, 'g': 5}
假设有一本字典,root
,它由 key:value 对组成,其中一些值本身就是字典。
能否(如果可以,如何)通过字典理解解压这些子词典?
例如
{k: v if type(v) is not dict else **v for k, v in root.items()}
示例:
root = {'a': 1, 'b': {'c': 2, 'd': 3}}
result = {'a': 1, 'c': 2, 'd': 3}
我想我应该 post 作为一个有更广泛解释的答案来帮助你,因为它与其他现有问题有点不同
{
_k: _v
for k, v in root.items()
for _k, _v in ( # here I create a dummy dictionary if non exists
v if isinstance(v, dict) else {k: v}
).items() # and iterate that
}
理解的关键部分是你需要一致和通用的逻辑才能使理解起作用。
您可以通过使用 v if isinstance(v, dict) else {k: v}
那么这是一个简单的嵌套字典拆包练习。
为了帮助您以后理解,我建议您写出代码,例如
res = dict()
for k,v in root.items():
d = v if isinstance(v, dict) else {k: v}
for _k, _v in d.items():
res[_k] = _v
并以此为基础倒推
有用的参考资料
- Putting a simple if-then-else statement on one line
- Nested dictionary comprehension python
如果你有多层嵌套字典,我建议你使用以下基于递归函数的解决方案:
def flatten(res, root):
for k,v in root.items():
if isinstance(v, dict):
flatten(res, v)
else:
res[k] = v
root = {'a': 1, 'b': {'c': 2, 'd': {'e': 5, 'f': 6}}}
result = {}
flatten(result, root)
print(result) # {'a': 1, 'c': 2, 'e': 5, 'f': 6}
这是一个递归的解决方案。在函数 _flatten_into_kv_pairs
中,我们遍历键和值对,如果值不是字典,则生成那些 keys/values。如果是,那么我们使用 yield from
构造递归调用 _flatten_into_kv_pairs
。函数 flatten_dict
只是一个 shell,它将 key/value 对的序列转回字典。
def _flatten_into_kv_pairs(dict_object):
for k, v in dict_object.items():
if isinstance(v, dict):
yield from _flatten_into_kv_pairs(v)
else:
yield k, v
def flatten_dict(dict_object):
return dict(_flatten_into_kv_pairs(dict_object))
root = {'a': 1, 'b': {'c': 2, 'd': 3, 'e': {'f': 4, 'g': 5}}}
print(flatten_dict(root))
输出:
{'a': 1, 'c': 2, 'd': 3, 'f': 4, 'g': 5}