Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamically accessing nested dictionary keys?

Is there some simple way to access nested dictionary key when at first you don't know which key you will be accessing?

For example:

dct = {'label': 'A', 'config': {'value': 'val1'}}

In this dictionary I will need to access either label key or value key inside another dict that is accessible through config key.

It depends on state.

For example if we have variable called label, so if:

label = True
if label:
   key = 'label'

in this case its kind of easy:

dct[key]

Now if label is false and I need to access nested dictionary, how can I dynamically specify it so I would not need to use ifs on every iterated item (I mean check everytime if label is used instead of value, because I will know that before starting iteration on dictionary full of dct dictionaries)?

like:

label = False
if label:
   key = 'label'
else:
    key = 'config..?' # it should be something like ['config']['value']
like image 715
Andrius Avatar asked Oct 02 '16 15:10

Andrius


People also ask

How do you access nested dictionary items in Python?

To access a nested dictionary value in Python, you need to: Access the dictionary inside of a dictionary by its key. Access the value of the accessed dictionary by the associated key.

How does Python handle nested dictionary?

Addition of elements to a nested Dictionary can be done in multiple ways. One way to add a dictionary in the Nested dictionary is to add values one be one, Nested_dict[dict][key] = 'value'. Another way is to add the whole dictionary in one go, Nested_dict[dict] = { 'key': 'value'}.


2 Answers

Expanding on @Barun's work, and possibly helping answer @Bhavani's question re setting values in a nested dictionary, here is a generalised solution to dynamically accessing or setting nested dictionary keys. Python 3.7.

from typing import List

class DynamicAccessNestedDict:
    """Dynamically get/set nested dictionary keys of 'data' dict"""

    def __init__(self, data: dict):
        self.data = data

    def getval(self, keys: List):
        data = self.data
        for k in keys:
            data = data[k]
        return data

    def setval(self, keys: List, val) -> None:
        data = self.data
        lastkey = keys[-1]
        for k in keys[:-1]:  # when assigning drill down to *second* last key
            data = data[k]
        data[lastkey] = val

You just wrap your dictionary in an instance of this class, then get and set by passing a list of keys.

dct = {'label': 'A', 'config': {'value': 'val1'}}

d = DynamicAccessNestedDict(dct)
assert d.getval(["label"]) == "A"
assert d.getval(["config", "value"]) == "val1"

# Set some new values
d.setval(["label"], "B")
d.setval(["config", "value"], "val2")

assert d.getval(["label"]) == "B"
assert d.getval(["config", "value"]) == "val2"
like image 69
abulka Avatar answered Sep 19 '22 18:09

abulka


If you know the key to be traversed, you can try out the following. This would work for any level of nested dicts.

dct = {'label': 'A', 'config': {'value': 'val1'}}

label = True
key = ('label',)
if not label:
    key = ('config', 'value')

ret = dct
for k in key:
  ret = ret[k]

print ret
like image 43
Barun Sharma Avatar answered Sep 17 '22 18:09

Barun Sharma