密码py公司
:
from itertools import product
from pprint import pprint as pp
all_objs = [{
"a": 1,
"b": [{"ba": 2, "bb": 3}, {"ba": 21, "bb": 31}],
"c": 4,
#"d": [{"da": 2}, {"da": 5}],
}, {
"a": 11,
"b": [{"ba": 22, "bb": 33, "bc": [{"h": 1, "e": 2}]}],
"c": 44,
}]
def flatten_dict(obj, parent_key=None):
base_dict = dict()
complex_items = list()
very_complex_items = list()
for key, val in obj.items():
new_key = ".".join((parent_key, key)) if parent_key is not None else key
if isinstance(val, list):
if len(val) > 1:
very_complex_items.append((key, val))
else:
complex_items.append((key, val))
else:
base_dict[new_key] = val
if not complex_items and not very_complex_items:
return [base_dict]
base_dicts = list()
partial_dicts = list()
for key, val in complex_items:
partial_dicts.append(flatten_dict(val[0], parent_key=new_key))
for product_tuple in product(*tuple(partial_dicts)):
new_base_dict = base_dict.copy()
for new_dict in product_tuple:
new_base_dict.update(new_dict)
base_dicts.append(new_base_dict)
if not very_complex_items:
return base_dicts
ret = list()
very_complex_keys = [item[0] for item in very_complex_items]
very_complex_vals = tuple([item[1] for item in very_complex_items])
for product_tuple in product(*very_complex_vals):
for base_dict in base_dicts:
new_dict = base_dict.copy()
new_items = zip(very_complex_keys, product_tuple)
for key, val in new_items:
new_key = ".".join((parent_key, key)) if parent_key is not None else key
new_dict.update(flatten_dict(val, parent_key=new_key)[0])
ret.append(new_dict)
return ret
def main():
flatten = list()
for obj in all_objs:
flatten.extend(flatten_dict(obj))
pp(flatten)
if __name__ == "__main__":
main()
:
-
正如预期的那样,使用了递归
-
这是一般的,它也适用于我在我的2
nd公司
注释(对于具有多个键且值由具有多个元素的列表组成的输入dict),可以通过对
“d”
输入
. 此外,理论上它应该支持任何深度
-
展平dict
:获取输入字典并输出字典列表(因为输入字典可能会生成多个输出字典):
-
每个键都有一个“简单”(非列表)值,不变地进入输出字典
-
在这一点上
基础
输出字典已完成(如果输入字典将生成多个输出字典,则所有字典都将具有
字典键/值,如果它只生成一个输出字典,那么这将是
基础
一)
-
-
具有单个元素列表的键(“有问题”)-每个
可以
-
-
然后,将在所有展平字典列表上计算笛卡尔乘积(对于当前输入,只有一个列表具有一个元素)
-
输出字典,因此
基础
每一个
-
-
在这一点上
基础
字典(可能只有一个)已完成,如果没有包含多个元素的列表的值,则这是返回列表,否则必须执行以下所有操作
每个
列表中的词典
-
将
生成多个输出字典:
-
-
然后,对于每个产品项元素,需要根据列表顺序建立其键(对于当前输入,产品项将只包含一个元素,并且只有一个键)
-
不同的
输出字典,因此
基础
复制字典,并使用展平产品项的键/值进行更新
-
新词典将附加到输出词典列表中
-
使用
和
Python 2
-
INTORTO受骗
:)),可能有一个更简单的实现,我错过了。
输出
c:\Work\Dev\StackOverflow\q046341856>c:\Work\Dev\VEnvs\py35x64_test\Scripts\python.exe code.py
[{'a': 1, 'b.ba': 2, 'b.bb': 3, 'c': 4},
{'a': 1, 'b.ba': 21, 'b.bb': 31, 'c': 4},
{'a': 11, 'b.ba': 22, 'b.bb': 33, 'b.bc.e': 2, 'b.bc.h': 1, 'c': 44}]
@编辑0
:
-
圣
-
纠正了一个逻辑错误,该错误被元组解包和笛卡尔乘积掩盖了:
if not complex_items ...
部分
: