Python Creating new dict from specific keys in other dict (nested)

Viewed 142

(Please note I searched and couldn't find an answer for this type of nested, with dict and lists, and with keeping keys names and values).

I'm trying to create a new dict from existing dict with specific keys-value pairs that I need.

Example/origin dict:

{
    "test1":{
        "test2":[
            
        ]
    },
    "test3":[
        
    ],
    "test4":{
        "test5":0,
        "what":{
            "in":"2",
            "out":"4"
        }
    },
    "test12":[
        {
            "in2":"a",
            "out2":"b"
        },
        {
            "in2":"a33",
            "out2":"b33"
        }
    ],
    "test9":255
}

I want to select keys for example: ['test1'], ['test4'], ['test12']['in2'] in such way that the result dict will be:

{
    "test1":{
        "test2":[
            
        ]
    },
    "test4":{
        "test5":0,
        "what":{
            "in":"2",
            "out":"4"
        }
    },
    "test12":[
        {
            "in2":"a"
        },
        {
            "in2":"a33"
        }
    ]
}

I'm aware its possible to do manually, i want to see the pythonic way :)

Thanks!!!

2 Answers

Try a dictionary comprehension with isinstance list:

>>> {k: ([{'in2': i['in2']} for i in v] if isinstance(v, list) else v) for k, v in dct.items() if not isinstance(v, int) and v}
{'test1': {'test2': []},
 'test4': {'test5': 0, 'what': {'in': '2', 'out': '4'}},
 'test12': [{'in2': 'a'}, {'in2': 'a33'}]}
>>> 

I don't think there is one "pythonic" way to do what you want here as there is an infinite number of possible values for your nested dict.

Here is a start of answer that you can adapt to your need !

import copy

def _transform(source_dict: dict, keys_to_keep: list):
   dict_copy = copy.deepcopy(source_dict)  # no side-effects
   
   for key, value in source_dict.items():
       if key not in keys_to_keep:
         dict_copy.pop(key)
       elif isinstance(value, dict):
         dict_copy[key] = _transform(value, keys_to_keep)
       elif isinstance(value, list):
         dict_copy[key] = [
             _transform(el, keys_to_keep) if isinstance(el, dict) else el for el in value
         ]
   return dict_copy
Related