"I want to check if the dictionary (say gen_dict
) has that value stored at that location and if not, update it."
But why? If it's the same value, updating won't change it so it'll effectively remain unchanged....
Suggested Solution 1
You can loop through the keys in topics
[except for the last one] and check if they're paired to a dictionary with .get
and isinstance
.
# topics = ['general_topic', 'born', 'to', 'fly']
set_val = 100
cur_dict = gen_dict ## gen_dict MUST BE a dictionary
for k in topics[:-1]:
if isinstance(cur_dict.get(k), dict): cur_dict = cur_dict[k]
cur_dict[topics[-1]] = set_val
# if topics[-1] in cur_dict: cur_dict[topics[-1]] = set_val ## only set if path exists
# if cur_dict[topics[-1]]!=set_val: cur_dict[topics[-1]] = set_val # redundant condition
This is quite forgiving, so even if some keys are missing, it will still work
{'other': 'blah', 'general_topic': {'born': {'to': {'fly': 30}}}, 'another': 324}
(from your comment) will become
{'other': 'blah', 'general_topic': {'born': {'to': {'fly': 100}}}, 'another': 324}
{'born': {'fly': 30}}
will become {'born': {'fly': 100}}
, but
{'born': {'to': 10}}
will become {'born': {'to': 10, 'fly': 100}}
, and
- an empty dictionary (
{}
) will become {'fly': 100}
.
[The last 2 ({'born': {'to': 10}}
, {}
) will remain unchanged if you use the if topics[-1] in cur_dict
condition.]
Suggested Solution 2
If you want to create the path if any part is missing [with the first key being optional], then use .setdefault
as below.
set_val = 100
cur_dict = gen_dict ## gen_dict MUST BE a dictionary
for i, k in enumerate(topics[:-1]):
if not i and not isinstance(cur_dict.get(k), dict): continue
kval = cur_dict.setdefault(k, {})
if not isinstance(kval, dict): cur_dict[f'prev_{k}'], cur_dict[k] = kval, {}
cur_dict = cur_dict[k]
cur_dict[topics[-1]] = set_val
[If the first key is not optional, then omit the if...continue
line at the beginning of the loop; and using enumerate
should no longer be necessary, so you can go back to for k in topics[:-1]
.]
{'other': 'blah', 'general_topic': {'born': {'to': {'fly': 30}}}, 'another': 324}
will still become
{'other': 'blah', 'general_topic': {'born': {'to': {'fly': 100}}}, 'another': 324}
[just like before], but
{'born': {'fly': 30}}
will become {'born': {'fly': 30, 'to': {'fly': 100}}}
, and
{'born': {'to': 10}}
will become {'born': {'to': {'fly': 100}, 'prev_to': 10}}
, and
- an empty dictionary (
{}
) will become {'born': {'to': {'fly': 100}}}
.