Home > Software design >  Python nested dictionary append new key based on another list
Python nested dictionary append new key based on another list

Time:10-11

I have a nested dictionary and I want to push a new element on in based on the resulted list. My current code is working fine, but I want a generic solution of multilevel dictionary and multiple nested list elements. Basically, I want to make this portion dynamic based on the list path- N.B: The items on the list is dynamic

data['top_banner']['image']['global_image'] <---- path wil come from list element

Part of dictionary:

{
  "top_banner": {
    "image": {
      "global_image": {
        "alt": " ",
        "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
        "sizes": [
          {
            "src": "",
            "view": "100vw",
            "media": "(min-width:100px)",
            "intrinsicwidth": 0,
            "intrinsicheight": 0
          }
        ],
        "types": [
          "webp ",
          "jpg"
        ],
        "background": True,
        "intrinsicWidth": 2400,
        "intrinsicHeight": 2400
      }
    },
    "title": "Dine",
    "description": ""
  }
}

List path:

[['top_banner', 'image', 'global_image']]

Current code:

data['top_banner']['image']['global_image'].update({'intrinsicWidth': 200, 'intrinsicHeight': 300})

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this should be from the list 

Edit: using soln of Dani Mesejo, what if I have multiple nested list elements?

for path in src_path:
    reduce(lambda y, x: y[x], path, data).update({'intrinsicwidth': 200, 'intrinsicheight': 300})

CodePudding user response:

If I understood correctly, use functools.reduce to go down the nested path

from functools import reduce
import pprint

data = {
    "top_banner": {
        "image": {
            "global_image": {
                "alt": " ", "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
                "sizes": [
                    {
                        "src": "", "view": "100vw", "media": "(min-width:100px)",
                        "intrinsicwidth": 0, "intrinsicheight": 0
                    }
                ],
                "types": ["webp ", "jpg"],
                "background": True, "intrinsicWidth": 2400, "intrinsicHeight": 2400
            }
        },
        "title": "Dine", "description": ""
    }
}

path = ['top_banner', 'image', 'global_image']
reduce(lambda y, x: y[x], path, data).update({'intrinsicWidth': 200, 'intrinsicHeight': 300})
pprint.pprint(data)

Output

{'top_banner': {'description': '',
                'image': {'global_image': {'alt': ' ',
                                           'background': True,
                                           'intrinsicHeight': 300,
                                           'intrinsicWidth': 200,
                                           'sizes': [{'intrinsicheight': 0,
                                                      'intrinsicwidth': 0,
                                                      'media': '(min-width:100px)',
                                                      'src': '',
                                                      'view': '100vw'}],
                                           'src': 'path/to/file/5473cd34fadbb6a3-dine-1.jpg',
                                           'types': ['webp ', 'jpg']}},
                'title': 'Dine'}}

CodePudding user response:

you can use a recursive function:

def get_dict_element_by_path(dic, lst):
    if lst:
        return get_dict_element_by_path(dic[lst[0]], lst[1:])
    else:
        return dic

my_list = ['top_banner', 'image', 'global_image']
get_dict_element_by_path(data, my_list).update({'intrinsicWidth': 200, 'intrinsicHeight': 300})

CodePudding user response:

import types

data = {
    "top_banner": {
        "image": {
            "global_image": {
                "alt": " ",
                "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
                "sizes": [
                    {
                        "src": "",
                        "view": "100vw",
                        "media": "(min-width:100px)",
                        "intrinsicwidth": 0,
                        "intrinsicheight": 0,
                    }
                ],
                "types": ["webp ", "jpg"],
                "background": True,
                "intrinsicWidth": 2400,
                "intrinsicHeight": 2400,
            }
        },
        "title": "Dine",
        "description": "",
    }
}

paths = [["top_banner", "image", "global_image"]]


def recursive(data, path):
    if len(path) == 0:
        return data
    return recursive(data[path[0]], path[1:])


for path in paths:
    recursive(data, path).update({"intrinsicWidth": 200, "intrinsicHeight": 300})

print(data)

result :

{
    "top_banner": {
        "image": {
            "global_image": {
                "alt": " ",
                "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
                "sizes": [
                    {
                        "src": "",
                        "view": "100vw",
                        "media": "(min-width:100px)",
                        "intrinsicwidth": 0,
                        "intrinsicheight": 0,
                    }
                ],
                "types": ["webp ", "jpg"],
                "background": True,
                "intrinsicWidth": 200,
                "intrinsicHeight": 300,
            }
        },
        "title": "Dine",
        "description": "",
    }
}

CodePudding user response:

Or you can do it this way whitout recursion

data = {
    "top_banner": {
        "image": {
            "global_image": {
                "alt": " ",
                "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
                "sizes": [
                    {
                        "src": "",
                        "view": "100vw",
                        "media": "(min-width:100px)",
                        "intrinsicwidth": 0,
                        "intrinsicheight": 0,
                    }
                ],
                "types": ["webp ", "jpg"],
                "background": True,
                "intrinsicWidth": 2400,
                "intrinsicHeight": 2400,
            }
        },
        "title": "Dine",
        "description": "",
    }
}

paths = [["top_banner", "image", "global_image"]]
res = data

for path in paths:
    for p in path:
        res = res[p]
    res.update({"intrinsicWidth": 200, "intrinsicHeight": 300})


print(data)

and this is the result

{
    "top_banner": {
        "image": {
            "global_image": {
                "alt": " ",
                "src": "path/to/file/5473cd34fadbb6a3-dine-1.jpg",
                "sizes": [
                    {
                        "src": "",
                        "view": "100vw",
                        "media": "(min-width:100px)",
                        "intrinsicwidth": 0,
                        "intrinsicheight": 0,
                    }
                ],
                "types": ["webp ", "jpg"],
                "background": True,
                "intrinsicWidth": 200,
                "intrinsicHeight": 300,
            }
        },
        "title": "Dine",
        "description": "",
    }
}
  • Related