Search code examples
pythondictionarydictionary-comprehension

Iterate over values of nested dictionary


Nested_Dict =
    {'candela_samples_generic': {'drc_dtcs': {'domain_name': 'TEMPLATE-DOMAIN', 'dtc_all':{ 
    '0x930001': {'identification': {'udsDtcValue': '0x9300', 'FaultType': '0x11', 'description': 'GNSS antenna short to ground'}, 
    'functional_conditions': {'failure_name': 'short_to_ground', 'mnemonic': 'DTC_GNSS_Antenna_Short_to_ground'}},
    '0x212021': {'identification': {'udsDtcValue': '0x2120', 'FaultType': '0x21', 'description': 'ECU internal Failure'},
    'functional_conditions': {'failure_name': 'short_to_ground', 'mnemonic': 'DTC_GNSS_Antenna_Short_to_ground'}}}}}}
   
 Header = {
        'dtc_all': {
            'DiagnosticTroubleCodeUds': {'udsDtcValue': None, 'FaultType': None},
            'dtcProps': {'description': None},
            'DiagnosticTroubleCodeObd': {'failure_name': None}   
        }
    }
    
SubkeyList = ['0x930001','0x212021']

Expected Output:    
New_Dict= 
{'dtc_all': 
{'0x930001': {'DiagnosticTroubleCodeUds': {'udsDtcValue': '0x9300', 'FaultType': '0x11'}, 'dtcProps':{'description': 'GNSS antenna short to ground'}, 'DiagnosticTroubleCodeObd': {'failure_name':short_to_ground}}},
{'0x212021': {'DiagnosticTroubleCodeUds': {'udsDtcValue': '0x2120', 'FaultType': '0x21'}, 'dtcProps':{'description': 'ECU internal Failure'}, 'DiagnosticTroubleCodeObd': {'failure_name':short_to_ground}}}}

Reference question: Aggregating Inputs into a Consolidated Dictionary

Here Want to iterate inside the header dictionary over the values of the header dictionary, but with my code it is iterating over keys of dict not the values of dict. Take an element from the SubkeyList and one header keys at a time from the dictionary (there can be multiple header keys like dtc_all). Iterate inside the header dictionary over the values of the dictionary, such as 'udsDtcValue'.

For example:
  Main_Key = dtc_all
  Sub_Key = 0x212021
  Element = udsDtcValue

Pass these parameters to the function get_value_nested_dict(nested_dict, Main_Key, Sub_Key, Element). This function will return the element value. get_value_nested_dict func which is working as expected for Element value retriaval I've posted for the reference. At the same time, create a new dictionary and update the element value at the right place, such as 'udsDtcValue': '0x9300'. Also, ensure that the sequence of keys remains the same as in the header. Similarly, iterate inside the header dictionary over all the values of the dictionary, such as FaultType, description, until failure_name. Repeat these iterations for each element in the SubkeyList and append the results in the new_dict in the same sequence. Any suggestions on how to proceed?

def create_new_dict(Nested_Dict, Header, SubkeyList):
    new_dict = {}
    for sub_key in SubkeyList:
        sub_dict = {}
        for element, value in Header['dtc_all'].items():
            value = get_value_nested_dict(Nested_Dict, 'dtc_all', sub_key, element)
            if value:
                sub_dict[element] = value[0]
        new_dict[sub_key] = sub_dict
    return new_dict

Solution

  • Much, much better 🤓

    You'll need to make sure that for each part of the Header dictionary structure, we're not only iterating over the keys but also get into their nested structure to retrieve udsDtcValue, FaultType, description and failure_name from Nested_Dict.

    def get_value_from_nested_dict(nested_dict, path):
        for key in path:
            nested_dict = nested_dict.get(key, {})
            if not nested_dict:
                return None
        return nested_dict
    def create_new_dict(nested_dict, header, subkey_list):
        new_dict = {'dtc_all': {}}
        path_mappings = {'DiagnosticTroubleCodeUds': ['identification'], 'dtcProps': ['identification'], 'DiagnosticTroubleCodeObd': ['functional_conditions']}
        for sub_key in subkey_list:
            sub_dict_structure = {}
            for header_key, inner_keys in header['dtc_all'].items():
                header_sub_dict = {}
                for inner_key in inner_keys.keys():
                    base_path = ['candela_samples_generic', 'drc_dtcs', 'dtc_all', sub_key]
                    specific_path = path_mappings.get(header_key, [])
                    value_path = base_path + specific_path + [inner_key]
                    value = get_value_from_nested_dict(nested_dict, value_path)
                    if value is not None:
                        header_sub_dict[inner_key] = value
                if header_sub_dict:
                    sub_dict_structure[header_key] = header_sub_dict
            if sub_dict_structure:
                new_dict['dtc_all'][sub_key] = sub_dict_structure
        return new_dict