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": "",
}
}