简体   繁体   English

用映射字典更改字典的键

[英]Change keys of a dict with a mapping dict

I want to replace keys name of a dictionary by passing a mapping dict with a function that replace also nested keys. 我想通过传递一个映射字典来替换字典的键名,该函数还可以替换嵌套键。 The issue is that I have multiple keys named 'id' in nested dictionary and I want to rename these 'id' with specific names. 问题是我在嵌套字典中有多个名为“ id”的键,并且我想使用特定名称重命名这些“ ​​id”。

Initial dictionnary: 初始词典:

initial_dict = {'id': 1, 'netAmount': 10.2, 'modifiedOn': '2017-01-01',
                    'statusId': 3, 'approvalStateId': 3, 'approvalState': {'id': 3,'name':'Approved'}}

Mapping dict: 映射字典:

 mapping_dict = {'id': 'pr_id', 'netAmount': 'net_amount', 'modifiedOn': 'modified_date',
                'statusId': 'status_id', 'approvalStateId': 'approval_id','approvalState':{'id':'approv_id'}}

Desired output of the dictionary: 字典的所需输出:

    output_dict = {'pr_id': 1, 'net_amount': 10.2, 'modified_date': '2017-01-01',
                    'status_id': 3, 'approval_id': 3, 'approvalState': {'approv_id': 3, 'name': 'Approved'}}

What I did is this but it only replace keys of the first level of the dict and if I try to set nested keys in the mapping dict, I get an error. 我所做的是此操作,但是它仅替换了字典第一级的键,如果我尝试在映射字典中设置嵌套键,则会收到错误消息。

def map_fields(obj):
    new_obj = {}
    mapping_dict = {'id': 'pr_id', 'netAmount': 'net_amount', 'modifiedOn': 'modified_date',
                    'statusId': 'status_id', 'approvalStateId': 'approval_id','approvalState':{'id':'approv_id'}}
    for key in obj.keys():
        if key in mapping_dict:
            new_key = mapping_dict[key]
        else:
            new_key = key
        new_obj[new_key] = obj[key]
    return new_obj

Do you have any idea how to do it? 你有什么想法吗?

Thanks 谢谢

You need a recursive function to be able to step up through the nested dictionaries. 您需要一个递归函数才能逐步完成嵌套字典。 The key is that when recursing, you need to pass both the child dictionary, and the child mapping dictionary. 关键是递归时,您需要同时传递子字典和子映射字典。

Note that the structure of your mapping dict is specific to this problem, and doesn't allow you to change the key of a nested dictionary - you'd need to restructure how you store the mapping to achieve that. 请注意,映射字典的结构特定于此问题,并且不允许您更改嵌套字典的键-您需要重组存储映射的方式才能实现此目的。

The following should do what you want (print statements added to help follow the logic when it runs): 以下应该做您想做的(添加打印语句以帮助其在运行时遵循逻辑):

def map_fields(init_dict, map_dict, res_dict=None):

    res_dict = res_dict or {}
    for k, v in init_dict.items():
        print("Key: ", k)
        if isinstance(v, dict):
            print("value is a dict - recursing")
            v = map_fields(v, map_dict[k])
        elif k in map_dict.keys():
            print("Remapping:", k, str(map_dict[k]))
            k = str(map_dict[k])
        res_dict[k] = v
    return res_dict

print(map_fields(initial_dict, mapping_dict))

Also if you want the same result but do not want to use a nested mapping dict such as : 另外,如果您希望获得相同的结果,但又不想使用嵌套的映射字典,例如:

mapping_dict = {'id': 'pr_id', 'netAmount': 'net_amount', 'modifiedOn': 'modified_date',
            'statusId': 'status_id', 'approvalStateId': 'approval_id', 'id':'approv_id'}

(ie 'id'/'approv_id' is not nested in 'approvalState') (即“ id” /“ approv_id”未嵌套在“ approvalState”中)

You can use the slightly different function: 您可以使用稍有不同的功能:

def map_fields(init_dict, map_dict, res_dict=None):
    res_dict = res_dict or {}
    for k, v in init_dict.items():
        if isinstance(v, dict):
            v = map_fields(v, map_dict)
        if k in map_dict.keys():
            k = str(map_dict[k])
        res_dict[k] = v
    return res_dict

This can be especially useful if the key 'approvalState' was also to map (to something like 'resultState', ie if your result needed to be: 如果键“ approvalState”也要映射到(例如“ resultState”之类的东西,即如果您的结果需要是:

output_dict = {'pr_id': 1, 'net_amount': 10.2, 'modified_date': '2017-01-01',
     'status_id': 3, 'approval_id': 3, 'resultState': {'approv_id': 3, 'name': 'Approved'}}

In which case, you would just have had to add the key/value pair 'approvalState'/'resultState' in your mapping dict. 在这种情况下,您只需要在映射字典中添加键/值对“ approvalState” /“ resultState”即可。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM