[英]Flat nested dict, where new key will be tuple of all nested keys
我有這樣的命令:
previous_dict = {
'dict_1': 'dict_1',
'dict_2': {
'dict_2_1': 'dict_2_1',
'dict_2_2': 'dict_2_2'
},
'dict_3': 3,
'dict_4': None,
'dict_5': dict()
}
我編寫了一個函數,將所有鍵作為元組平整字典,其輸出為:
previously_expected_dict = {}
for key, value in previous_dict.items():
if type(value) == dict:
for k, v in value.items():
previously_expected_dict[(key, k)] = v
else:
previously_expected_dict[(key,)] = value
輸出:
print(previously_expected_dict)
{
('dict_1',): 'dict_1',
('dict_2', 'dict_2_1'): 'dict_2_1',
('dict_2', 'dict_2_2'): 'dict_2_2',
('dict_3',): 3,
('dict_4',): None
}
dict_5
由於沒有任何值而被丟棄
現在需求已更改,並且dict可以具有任意數量的嵌套
new_dict = {
'dict_1': {
'dict_1_1': {
'dict_1_1_1': 'dict_1_1_1',
'dict_1_1_2': 'dict_1_1_2'
}
},
'dict_2': {
'dict_2_1': 'dict_2_1',
'dict_2_2': 'dict_2_2'
},
'dict_3': 'dict_3',
'dict_4': dict()
}
到目前為止我嘗試過的代碼
def make_flat(my_dict):
nd = dict()
keys = []
def loop_me(value):
nonlocal keys
if isinstance(value, dict):
for k, v in value.items():
keys.append(k)
loop_me(v)
else:
nd[tuple(keys)] = value
keys.pop(-1)
loop_me(my_dict)
return nd
print(make_flat(new_dict))
但是我在元組中收到了額外的密鑰
{
('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1', # Perfect
('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2', # Perfect
('dict_1', 'dict_1_1', 'dict_2', 'dict_2_1'): 'dict_2_1', # Error, Expected is: ('dict_2', 'dict_2_1')
('dict_1', 'dict_1_1', 'dict_2', 'dict_2_2'): 'dict_2_2', # Error, Expected is: ('dict_2', 'dict_2_2')
('dict_1', 'dict_1_1', 'dict_2', 'dict_3'): 'dict_3' # Error, Expected is: ('dict_3',)
}
最終預期產出:
output = {
('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1',
('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2',
('dict_2', 'dict_2_1'): 'dict_2_1',
('dict_2', 'dict_2_2'): 'dict_2_2',
('dict_3',): 'dict_3'
}
我嘗試使用for循環和遞歸函數Failed編寫。
您可以使用遞歸:
def flatten(d, c = []):
for a, b in d.items():
if not isinstance(b, dict):
yield (tuple(c+[a]), b)
else:
yield from flatten(b, c+[a])
print(dict(flatten(previous_dict)))
輸出:
{('dict_1',): 'dict_1', ('dict_2', 'dict_2_1'): 'dict_2_1', ('dict_2', 'dict_2_2'): 'dict_2_2', ('dict_3',): 3, ('dict_4',): None}
隨着new_dict
:
{('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1', ('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2', ('dict_2', 'dict_2_1'): 'dict_2_1', ('dict_2', 'dict_2_2'): 'dict_2_2', ('dict_3',): 'dict_3'}
您可以使用一個函數來遍歷dict項,並將鍵添加到遞歸調用返回的子鍵元組中:
def flatten(d):
for k, v in d.items():
if isinstance(v, dict):
for s, i in flatten(v):
yield (k, *s), i
else:
yield (k,), v
這樣dict(flatten(new_dict))
返回:
{('dict_1', 'dict_1_1', 'dict_1_1_1'): 'dict_1_1_1', ('dict_1', 'dict_1_1', 'dict_1_1_2'): 'dict_1_1_2', ('dict_2', 'dict_2_1'): 'dict_2_1', ('dict_2', 'dict_2_2'): 'dict_2_2', ('dict_3',): 'dict_3'}
我使用了deep
變量來確定和更正鍵,並且make_flat
函數返回所需的輸出,但是,@ Ajax1234更清楚地做到了。
def make_flat(dict_):
new_dict = dict()
keys = []
def loop_recursively(value, deep=0):
nonlocal keys
if isinstance(value, dict):
deep += 1
for k, v in value.items():
keys.append(k)
loop_recursively(v, deep)
else:
deep -= 1
else:
keys = keys[-deep:]
new_dict[tuple(keys)] = value
keys.pop(-1)
loop_recursively(dict_)
return new_dict
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.