0

I have below below dictionary

{
  "person": {
    "name": "test_user"
  }
}

and I have nested path "person.name" and new value to which needs to be update on this path is let's say "test_user_2". I want to write a general function which can do the job something like below:

def update_data(data, nested_path, new_value):
    # do something
    return new_data

new_data should look like below:

{
  "person": {
    "name": "test_user_2"
  }
}
Timus
  • 10,974
  • 5
  • 14
  • 28

2 Answers2

0

If you sent your path as a list of keys you should find your answer here.

ramsluk
  • 104
  • 7
0

Here's a quick hack - I'm sure it can be shortened.

def find_value(idx: str, data: dict):
    field_name = idx.split('.')[0]
    if field_name in data:
        value = data[field_name]
        if isinstance(value, dict) and len(idx.split('.')) > 0:
            return find_value(idx='.'.join(idx.split('.')[1:]), data=value)
        else: 
            return value
    raise Exception('Key "{}" not found'.format(idx))


def replace_value(idx: str, data: dict, new_value, _new_data: dict=dict()):
    field_name = idx.split('.')[0]
    if field_name in data:
        value = data[field_name]
        if isinstance(value, dict) and len(idx.split('.')) > 0:
            new_dict = {**_new_data, **replace_value(idx='.'.join(idx.split('.')[1:]), data=value, new_value=new_value) }
            return {**_new_data, **{ field_name: new_dict} }
        else: 
            return {**_new_data, **{ field_name: new_value} }
    raise Exception('Key "{}" not found'.format(idx))


if __name__ == '__main__':
    data = {'person': {'name': 'test_user',}}
    index = 'person.name'
    print('Value pre-processing  : {}'.format(find_value(idx=index, data=data)))
    data = replace_value(idx=index, data=data, new_value='test_user_2')
    print('Value post-processing : {}'.format(find_value(idx=index, data=data)))
    print('data                  : {}'.format(data))

The output when run:

$ python3 test.py
Value pre-processing  : test_user
Value post-processing : test_user_2
data                  : {'person': {'name': 'test_user_2'}}
nicc777
  • 75
  • 1
  • 3