Сравнение словарей с большой вложенностью
(python) Задача такая: Имеется 2 словаря одинакового формата
{
(dict)tag1:[
(str)sub_tag1,
(dict)sub_tag2: {[
sub_sub_tag1 ... (str/dict)
]}
(str)sub_tag3,
(str)sub_tag4
...
(str/dict)sub_tagN
]
...
(str/dict)tagN
}
Важно вложенность может быть больше или меньше!
Каждый тег может быть строкой либо еще одним вложенным словарем при чем в словарях 1 и 2 выше по дереву вложенности может быть 2 одинаковых словаря ребенка но стоящих в разных местах в списке
Необходимо сделать функцию которая принимает на вход 2 словаря и отдает словарь изменений первого словаря относительно второго:
{
tag10: +
tag11: [
sub_tag: +
sub_tag: [
sub_sub_tag: -
]
]
}
при этом нужно учитывать что словари и строки во вложенностях могут быть просто в разных местах
примеры словарей:
d1
{'offer':
['type',
'property-type',
'category',
'mortgage',
'deal-status',
'creation-date',
'last-update-date',
{'location':
['country',
'locality-name',
'address',
'latitude',
'longitude',
'apartment']},
{'sales-agent':
['name',
'phone',
'category',
'organization',
'url',
'email',
'photo']},
{'price':
['value',
'currency']},
'image',
'image',
'image',
'image',
'image',
{'area':
['value',
'unit']},
{'kitchen-space':
['value',
'unit']},
'renovation',
'description',
'new-flat',
'floor',
'rooms',
'apartments',
'floors-total',
'building-name',
'yandex-building-id',
'yandex-house-id',
'building-state',
'built-year',
'ready-quarter',
'building-section']
}
d2
{
'offer':[
'type',
'property-type',
'category',
'mortgage',
'deal-status',
'creation-date',
'last-update-date',
{'location':
['country',
'locality-name',
'address',
'latitude',
'longitude',
'apartment']},
{'sales-agent':
['name',
'phone',
'category',
'organization',
'url',
'email',
'photo']},
{'price':
['value',
'currency']},
'image',
'image',
'image',
'image',
'image',
'image',
{'area':
['value',
'unit']},
{'living-space':
['value',
'unit']},
{'kitchen-space':
['value',
'unit']},
'renovation',
'description',
'new-flat',
'floor',
'rooms',
'apartments',
'floors-total',
'building-name',
'yandex-building-id',
'yandex-house-id',
'building-state',
'built-year',
'ready-quarter',
'building-section']
}
для наглядности
d1 {offer : ['type', 'property-type', 'category', 'mortgage', 'deal-status', 'creation-date', 'last-update-date', {'location': ['country', 'locality-name', 'address', 'latitude', 'longitude', 'apartment']}, {'sales-agent': ['name', 'phone', 'category', 'organization', 'url', 'email', 'photo']}, {'price': ['value', 'currency']}, 'image', 'image', 'image', 'image', 'image', {'area': ['value', 'unit']}, {'kitchen-space': ['value', 'unit']}, 'renovation', 'description', 'new-flat', 'floor', 'rooms', 'apartments', 'floors-total', 'building-name', 'yandex-building-id', 'yandex-house-id', 'building-state', 'built-year', 'ready-quarter', 'building-section']}
d2 {offer : ['type', 'property-type', 'category', 'mortgage', 'deal-status', 'creation-date', 'last-update-date', {'location': ['country', 'locality-name', 'address', 'latitude', 'longitude', 'apartment']}, {'sales-agent': ['name', 'phone', 'category', 'organization', 'url', 'email', 'photo']}, {'price': ['value', 'currency']}, 'image', 'image', 'image', 'image', 'image', 'image', {'area': ['value', 'unit']}, {'living-space': ['value', 'unit']}, {'kitchen-space': ['value', 'unit']}, 'renovation', 'description', 'new-flat', 'floor', 'rooms', 'apartments', 'floors-total', 'building-name', 'yandex-building-id', 'yandex-house-id', 'building-state', 'built-year', 'ready-quarter', 'building-section']}
Я пока вижу рекурсивную функцию с 2 проходами сначала по первому словарю для определения новых тегов потом по второму словарю для определения тегов которых нет в первом (однако застрял на определении одинаковых словарей если они различаются только одним вложеным тегом например и находятся в разных местах в списке)
мой набросок
def findDiff1(dict_1, dict_2):
changes = {}
for key in dict_1:
if key not in dict_2:
changes[key] = '+'
else:
for item in dict_1[key]:
if type(item) is dict:
# todo find dict in arr on key of dict
if item in dict_2[key]:
findDiff1(item, dict_2[key] # dict)
else:
changes[key] = {}
changes[key][item[0]]
elif type(item) is str:
if item not in dict_2:
changes[key] = {}
changes[key][item] = '+'
# next for on dict_2
return changes
Ответы (1 шт):
А вариант через готовые модули вас не устроит? что-то типа jsondiff?
Как-нибудь так:
import json
import jsondiff
j1 = json.loads(str(d1).replace("'", '"'))
j2 = json.loads(str(d2).replace("'", '"'))
res = jsondiff.diff(j1, j2)
ну и res будет:
{'offer': {insert: [(10, 'image'), (17, {'living-space': ['value', 'unit']})]}}
# ключ, позиция, ключ или значение