多级字典嵌套解析合并,两嵌套字典对不返不同

发布时间 2023-08-27 14:50:55作者: Οo白麒麟оΟ

1.字典解析与合并

class ConfigConverter:
    """
    get source translate data, merge translate data and source data
    """

    translate_v = ["value"]
    translate_n = ["name"]
    translate_v_and_sub = [
        "value",
        ("sub_list", ["value"]),
    ]
    translate_n_category = ["name", "category_value"]
    translate_v_category = ["value", "category_value"]
    translate_country_lists = [
        "value",
        ("region_lists", ["display_name", ("location_lists", ["value"])]),
    ]
    translate_address_lists = [
        "name",
        ("countrys", ["name", ("regions", ["name"])]),
    ]
    translate_location_lists = [
        "value",
        "display_name",
        ("locations", ["value", "region_display_name"]),
    ]
    translate_title_description_category = ["title", "description", "category_value"]
    translate_title_description = ["title", "description"]
    translate_title = ["title"]
    translate_main_job_function_lists = [
        "value",
        (
            "sub_function_list",
            [
                "value",
                ("job_titles", ["value"]),
                ("skills", ["value"]),
            ],
        ),
    ]
    translate_v_permissions = ["value", ("permissions", ["value"])]

    def __init__(self):
        self.translate_maps = {
            "xp_lvls": self.translate_v,
            "job_types": self.translate_v,
            "degrees": self.translate_v,
            "no_of_employee_ranges": self.translate_v,
            "company_sizes": self.translate_v,
            "industry_lists": self.translate_v,
            "job_category_lists": self.translate_v_and_sub,
            "job_benefit_lists": self.translate_n_category,
            "job_attractive_reasons": self.translate_v,
            "company_benefit_lists": self.translate_v_category,
            "company_culture_lists": self.translate_v_category,
            "company_financing_stage_lists": self.translate_v,
            "country_lists": self.translate_country_lists,
            "address_lists": self.translate_address_lists,
            "location_lists": self.translate_location_lists,
            "chat_report_lists": self.translate_v,
            "notice_period_lists": self.translate_v,
            "subscibe_job_frequency_lists": self.translate_v,
            "report_job_reasons": self.translate_title_description_category,
            "report_talent_reasons": self.translate_title_description,
            "gender_lists": self.translate_v,
            "pipeline_stage_lists": self.translate_v,
            "resume_last_updated_time_lists": self.translate_v,
            "main_job_function_lists": self.translate_main_job_function_lists,
            "report_interview_reasons": self.translate_title_description,
            "report_recruiter_reasons": self.translate_title_description,
            "report_company_reasons": self.translate_title_description,
            "work_xps": self.translate_v,
            # "educations": self.translate_v,
            "salary_range_filters": self.translate_v,
            "users": self.translate_v,
            "jobs": self.translate_v,
            # "company_documents": self.translate_v,
            "recruiter_documents": self.translate_v,
            "job_seeker_work_xps": self.translate_v,
            "job_seeker_prefs": self.translate_v,
            "job_seeker_edus": self.translate_v,
            "saved_jobs": self.translate_v,
            "saved_candidates": self.translate_v,
            "blacklisted_users": self.translate_v,
            "blacklisted_companies": self.translate_v,
            "job_seeker_resumes": self.translate_v,
            "job_applications": self.translate_v,
            "dialogues": self.translate_v,
            # "chats": self.translate_v,
            "interview_result": self.translate_v,
            "recruiter_role_permissions": self.translate_v_permissions,
            # "feature_banners": self.translate_title,
            "recruiter_chat_type_filters": self.translate_v,
            "recruiter_chat_status_filters": self.translate_v,
            "jobseeker_chat_type_filters": self.translate_v,
            "company_types": self.translate_v,
            "recruiter_badge_types": self.translate_n,
            "recruiter_badge_tiers": self.translate_n,
        }

    def gen_translate_data(
        self, source_data, translate_map, translate_data, current_key
    ):
        for _, item in enumerate(source_data):
            for map_key in translate_map:
                if isinstance(map_key, str):
                    key = ".".join([current_key, str(item["id"]), map_key])
                    translate_data[key] = item[map_key]
                elif isinstance(map_key, tuple):
                    v_key = map_key[0]
                    key = ".".join([current_key, str(item["id"]), map_key[0]])

                    value = item[v_key]
                    new_map_key = map_key[1]
                    self.gen_translate_data(value, new_map_key, translate_data, key)

    def gen_translate_key_values(self, source_data, translate_data, current_key=""):
        for key, value in source_data.items():
            if key in self.translate_maps and isinstance(value, list):
                if current_key:
                    key = ".".join([current_key, key])
                if key.startswith("country_diff"):
                    translate_map = self.translate_maps[key.split(".")[-1]]
                else:
                    translate_map = self.translate_maps[key]
                self.gen_translate_data(value, translate_map, translate_data, key)
            elif isinstance(value, dict):
                if current_key:
                    key = ".".join([current_key, key])
                self.gen_translate_key_values(value, translate_data, key)
        return translate_data

    def merge_translate_data(
        self, source_data, translate_map, translate_data, current_key
    ):
        for index, item in enumerate(source_data):
            for map_key in translate_map:
                if isinstance(map_key, str):
                    key = ".".join([current_key, str(item["id"]), map_key])
                    if translate_data.get(key):
                        item[map_key] = translate_data[key]
                elif isinstance(map_key, tuple):
                    v_key = map_key[0]
                    key = ".".join([current_key, str(item["id"]), map_key[0]])

                    value = item[v_key]
                    new_map_key = map_key[1]
                    source_data[index][v_key] = self.merge_translate_data(
                        value, new_map_key, translate_data, key
                    )
        return source_data

    def merge_translate_key_values(
        self, source_data: dict, translate_data: dict, country_key: str
    ):
        country_diff_prefix = "country_diff_"
        current_country_diff_prefix = f"country_diff_{country_key}."

        for key, value in list(translate_data.items()):
            if key.startswith(country_diff_prefix):
                if not key.startswith(current_country_diff_prefix):
                    del translate_data[key]
                else:
                    new_key = key[len(current_country_diff_prefix) :]
                    translate_data[new_key] = value
                    del translate_data[key]

        for key, _value in list(source_data.items()):
            value = copy.deepcopy(_value)
            if key in self.translate_maps and isinstance(value, list):
                translate_map = self.translate_maps[key]
                data = self.merge_translate_data(
                    value, translate_map, translate_data, key
                )
                source_data[key] = data

        return source_data

使用:
data_2 = {
"address_lists": [
{
"id": "1",
"level": "1",
"name": "亚洲",
"countrys": [
{
"id": "7",
"level": "2",
"name": "中国",
"regions": [
{
"id": "247",
"level": "3",
"name": "北京"
},
{
"id": "248",
"level": "3",
"name": "天津"
}
]}
]
},
{
"id": "156",
"level": "1",
"name": "Antarctica",
"countrys": [
{
"id": "157",
"level": "2",
"name": "South Georgia and South Sandwich Islands",
"regions": [
]
},
{
"id": "169",
"level": "2",
"name": "Georgia",
"regions": [

]
}
]
}
]}
from core.config_converter import ConfigConverter
# cc = ConfigConverter()
# data = cc.merge_translate_key_values(data_2, data_3, "")
# print(data)

cc = ConfigConverter()
translate_data = {}
cc.gen_translate_key_values(dict_1, translate_data)
print(translate_data)

 

2.嵌套字典比较取不同

def compare_list_value(dict1, dict2):
    diff_dict1 = {}
    diff_dict2 = {}

    for key in dict1:
        if key in dict2:
            if isinstance(dict1[key], list) and isinstance(dict2[key], list):
                diff_dict1[key] = []
                diff_dict2[key] = []
                for i, item1 in enumerate(dict1[key]):
                    if i < len(dict2[key]):
                        item2 = dict2[key][i]
                        if item1 != item2:
                            if isinstance(item1, dict) and isinstance(item2, dict):
                                diff_item1 = {
                                    k: v
                                    for k, v in item1.items()
                                    if item1.get(k) != item2.get(k)
                                }
                                diff_item2 = {
                                    k: v
                                    for k, v in item2.items()
                                    if item2.get(k) != item1.get(k)
                                }
                                if diff_item1:
                                    diff_dict1[key].append(diff_item1)
                                if diff_item2:
                                    diff_dict2[key].append(diff_item2)
                            else:
                                diff_dict1[key].append(item1)
                                diff_dict2[key].append(item2)
                    else:
                        diff_dict1[key].append(item1)
                if len(dict2[key]) > len(dict1[key]):
                    diff_dict2[key].extend(dict2[key][len(dict1[key]) :])
            else:
                if dict1[key] != dict2[key]:
                    diff_dict1[key] = dict1[key]
                    diff_dict2[key] = dict2[key]
        else:
            diff_dict1[key] = dict1[key]
    for key in dict2:
        if key not in dict1:
            diff_dict2[key] = dict2[key]
    return diff_dict1, diff_dict2