Home > database >  Create new nested dictionary using nested key, values
Create new nested dictionary using nested key, values

Time:12-03

I have a dictionary of key-value pairs, where the value is itself a dictionary. I would like to change the names of key values in that nested dictionary based on a predefined conversion.

I am using two lists to match up the values of the nested keys that I am trying to conver (Old_item1 should become New_item1):

comparison_list = ['Old_item1', 'Old_item2']
new_prods = ['New_item1', 'New_item2']

old_dict = {
    'Company1':
        {
            'Old_item1':
                {
                    'key1': val,
                    'key2': val
                },
            'Old_item2':
                {
                    'key1': val,
                    'key2': val
                }
        }
}

I tried this:

new_dict = {}
for i in comparison_list:
    for j in new_prods:
        new_dict['Company1'][j] = test['Company1'][i] 

I get a KeyError: KeyError: 'Company1'

The desired output for each item I add to each list is:

new_dict = {
    'Company1':
        {
            'New_item1':
                {
                    'key1': val  # old item key, val
                    'key2': val  # old item key, val
                }
        }
}

CodePudding user response:

You can make a dictionary of mappings from the old to the new items, and then use it to create a new sub-dictionary for each company. This then needs to be wrapped inside an outer loop over companies (although here there is only one).

For example:

comparison_list = ['Old_item1', 'Old_item2']
new_prods = ['New_item1', 'New_item2']
    
old_dict = {'Company1': 
            {'Old_item1': 
             {'key1': 2, 
              'key2': 3},
             'Old_item2': 
             {'key1': 4,
              'key2': 5}}} 

key_mappings = dict(zip(comparison_list, new_prods))

new_dict = {k: {key_mappings[k1]: v1 for k1, v1 in v.items()}
            for k, v in old_dict.items()}

print(new_dict)

gives:

{'Company1': {'New_item1': {'key1': 2, 'key2': 3}, 'New_item2': {'key1': 4, 'key2': 5}}}

Here is the mappings dictionary key_mappings which we used:

{'Old_item1': 'New_item1', 'Old_item2': 'New_item2'}

CodePudding user response:

The easiest way to go about this is to re-create your dictionary with a comprehension:

new_dict = {company: update_item(v) for company, v in old_dict.items()}

Then parse out update_item to it's own function. You could do this inline but it makes it difficult to understand.

conversion_lookup = {
    'Old_item1': 'NewItem1',
    'Old_item2': 'NewItem2',
}

def update_item(item: dict) -> dict:
    return { conversion_lookup.get(k, k): v for k, v in item.items() }

new_dict = {company: update_item(v) for company, v in old_dict.items()}

For the conversion here I'm using a dictionary describing the conversion. If you need to construct this automatedly:

comparison_list = ['Old_item1', 'Old_item2']
new_prods = ['New_item1', 'New_item2']

conversion_lookup = { v: new_prods[idx] for idx, v in enumerate(comparison_list) }

The reason I like a dictionary is that you can use some_dict.get(a_value, a_default_value). Then, if your value isn't in your conversion dictionary you can fall back to the original value. That's what I'm doing here:

conversion_lookup.get(k, k)

The second k is the original item's value, which is a good thing to use if your conversion list doesn't include what you want.

CodePudding user response:

One approach is to do it step by step. First create the dicts with the new names and old keys, then remove the old keys, and finally add in the new names.

# Keep the values from the old keys
values = [old_dict['Company1'][old_name] for old_name in comparison_list]

# Remove old names, and add in the 
for new_key, value, old in zip(new_prods, values, comparison_list):
    old_dict['Company1'].pop(old)
    old_dict['Company1'][new_key] = value

  • Related