Как из одного словаря, скопировать значение в другой словарь, со вложенным словарем?
Дано:
a_dict- словарь (14 ключей id), со вложенными словарями, в которых есть пустые значенияvalueb_dict- словарь (12 ключей id), со вложенными словарями, в котором есть заполненные значенияvalue
Нужно:
Заполнить a_dict значениями из b_dict по соответствующим ключам id (id не по порядку и в a_dict останутся пустые значения, так как id в нем 14)
Первый словарь:
a_dict = {
"tests": [{
"id": 1,
"title": "S",
"value": ""
}, {
"id": 2,
"title": "D",
"value": ""
}, {
"id": 3,
"title": "P",
"value": "",
"values": [{
"id": 31,
"title": "M",
"value": "",
"values": [ {
"id": 311,
"title": "P",
"values": [{
"id": 3111,
"title": "f",
"value": ""
}, {
"id": 3112,
"title": "f",
"value": ""
}]
}]
}, {
"id": 32,
"title": "S",
"value": "",
"values": [ {
"id": 321,
"title": "P",
"values": [{
"id": 3211,
"title": "s",
"value": ""
}, {
"id": 3212,
"title": "h",
"value": ""
}]
}]
}]
}, {
"id": 4,
"title": "S",
"value": "",
"values": [{
"id": 41,
"title": "C",
"value": ""
}, {
"id": 42,
"title": "I",
"value": ""
}]
}]
}
Второй словарь:
b_dict = {
"values": [{
"id": 42,
"value": "passed"
}, {
"id": 1,
"value": "passed"
}, {
"id": 31,
"value": "passed"
}, {
"id": 3,
"value": "failed"
}, {
"id": 2,
"value": "failed"
}, {
"id": 311,
"value": "passed"
}, {
"id": 3111,
"value": "passed"
}, {
"id": 3212,
"value": "passed"
}, {
"id": 4,
"value": "passed"
}, {
"id": 41,
"value": "failed"
}, {
"id": 3211,
"value": "passed"
}, {
"id": 321,
"value": "failed"
}]
}
Перечитал много про вложенные словари, но в итоге даже не могу даже распечатать вложенные словари через цикл из a_dict, чтобы заменить value.
for t in a_dict["tests"]:
print(("{} "*len(t)).format(t.get('id'), t.get("value"), t.get('title'), t.get('values')))
Подскажите в какую сторону копать. Ощущение, что я что-то упускаю, и будет в итоге что-то типа:
for i in range(len(b_dict['values'])):
if a_dict[id] == b_dict[id]:
a_dict['tests'][i]['value'] = b_dict['values'][i]['value']
Только так меняется только одно значение, а как добраться до остальных value в a_dict, если они так неравномерно вложены?
id в a_dict перебором находятся так:
print(a_dict["tests"][0]['id']) # 2
print(a_dict["tests"][1]['id']) # 41
print(a_dict["tests"][2]['id']) # 73
print(a_dict["tests"][2]["values"][0]['id']) # 345
print(a_dict["tests"][2]["values"][0]["values"][0]['id']) # 230
print(a_dict["tests"][2]["values"][0]["values"][0]["values"][0]['id']) # 234
print(a_dict["tests"][2]["values"][0]["values"][0]["values"][1]['id']) # 653
print(a_dict["tests"][2]["values"][1]['id']) # 110
print(a_dict["tests"][2]["values"][1]["values"][0]['id']) # 261
print(a_dict["tests"][2]["values"][1]["values"][0]["values"][0]['id']) # 238
print(a_dict["tests"][2]["values"][1]["values"][0]["values"][1]['id']) # 690
print(a_dict["tests"][3]['id']) # 122
print(a_dict["tests"][3]["values"][0]['id']) # 5321
print(a_dict["tests"][3]["values"][1]['id']) # 5322
Ответы (1 шт):
Можно воспользоваться рекурсивной функцией:
def set_value(d):
if not isinstance(d, dict):
return d
if d.get("value"):
return d
r = [x.get("value") for x in b_dict["values"] if x.get("id") == d.get("id")]
if r and r[0]:
d["value"] = r[0]
return d
def apply_recursive(func, obj):
if isinstance(obj, list):
return [apply_recursive(func, elem) for elem in obj]
elif isinstance(obj, dict):
obj = func(obj)
return {k: apply_recursive(func, v) for k, v in obj.items()}
else:
return func(obj)
вызов:
_ = apply_recursive(set_value, a_dict)
результат:
In [106]: a_dict
Out[106]:
{'tests': [{'id': 1, 'title': 'S', 'value': 'passed'},
{'id': 2, 'title': 'D', 'value': 'failed'},
{'id': 3,
'title': 'P',
'value': 'failed',
'values': [{'id': 31,
'title': 'M',
'value': 'passed',
'values': [{'id': 311,
'title': 'P',
'values': [{'id': 3111, 'title': 'f', 'value': 'passed'},
{'id': 3112, 'title': 'f', 'value': ''}],
'value': 'passed'}]},
{'id': 32,
'title': 'S',
'value': '',
'values': [{'id': 321,
'title': 'P',
'values': [{'id': 3211, 'title': 's', 'value': 'passed'},
{'id': 3212, 'title': 'h', 'value': 'passed'}],
'value': 'failed'}]}]},
{'id': 4,
'title': 'S',
'value': 'passed',
'values': [{'id': 41, 'title': 'C', 'value': 'failed'},
{'id': 42, 'title': 'I', 'value': 'passed'}]}]}