Home > Blockchain >  Set nested dictionary value by index
Set nested dictionary value by index

Time:06-22

After Python 3.7, dictionaries are order-preserving. This allows us to get values as follows:

a = list(dict.values())[idx]

What I want to do is to set a value, which is nested as follows. There is an outer dictionary, its first value is an instance of a class. This class has another dictionary as attribute, and I would like to change the first value in this dictionary.

a = list(list(outer_dict.values())[0].dict_as_attribute.values())[0]
a = 1

How do I put the new a back to its place? The above expression gives me a copy, and when I change a, the one in the dictionary stays the same. Ofcourse, the following also doesn't work:

list(list(outer_dict.values())[0].attribute.values())[0] = a

Solutions using known keys or using different data structures don't help: I am not allowed to change the data structure and I also do not know the keys.

Thanks for the answers.

CodePudding user response:

You can get the keys in the same way as you get the values:

outer_key = list(outer_dict.keys())[0]
inner_key = list(list(outer_dict.values())[0].attribute.keys())[0]
outer_dict[outer_key].attribute[inner_key] = a

CodePudding user response:

outer_key = next(iter(outer_dict.keys()))
inner_key = next(iter(outer_dict[outer_key].dict_as_attribute.keys()))
outer_dict[outer_key].dict_as_attribute[inner_key] = a

This avoids creating lists containing all the keys, so is more efficient.

CodePudding user response:

You need to keep a reference to the dict key, you want to change:

# dummy class
class A:
    def __init__(self):
        self.dict_as_attribute = {
            'foo': 'FOO',
            'bar': 'BAR',
            'baz': 'BAZ'
        }


outer_dict = {
    chr(k): A() for k in range(80, 85)
}


outerIndexToChange = 3
innerIndexToChange = 2
newValue = 'FOOBAR'

# change dict value
outerReference = outer_dict[list(outer_dict.keys())[outerIndexToChange]].dict_as_attribute
outerReference[list(outerReference.keys())[innerIndexToChange]] = newValue


# verify
for v in outer_dict.values():
    print(v.dict_as_attribute)

Out:

{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'FOOBAR'}
{'foo': 'FOO', 'bar': 'BAR', 'baz': 'BAZ'}
  • Related