1

I would like to be able to use a single "nested_key" variable to get a value from an (arbitrarily deep) set of nested dicts.

If I have a dict of dicts I can simply index it like so:

a = {"Alice": {"Car": {"Color": "Blue"}}}
a["Alice"]["Car"]["Color"]
>>> "Blue"

But I don't think(?) I can easily make that chain of indexes into a variable and use it in the same way?

a = {"Alice": {"Car": {"Color": Blue}}}
nested_key = ["Alice"]["Car"]["Color"] # for use in: a[nested_key]
>>> TypeError: list indicies must be integer, not str

Lists have the slice() object; but is there a way to assign a 'key-like' object to a variable?

Otherwise I suppose a recursive_get style function (e.g. https://stackoverflow.com/a/28225660/2588039) is probably my best bet?

David258
  • 697
  • 2
  • 6
  • 15
  • The recursive style function seems like the best way. Of course, you can always replace recursion by iteration. Either way, there's no slick oneliner here. – timgeb Sep 10 '18 at 14:48
  • 1
    Closed as duplicate because the answers start to mimic the answer from ... the duplicate. – timgeb Sep 10 '18 at 14:53
  • For some further inspiration, you can take a look at the [Accessor class from django-tables2](https://github.com/jieter/django-tables2/blob/master/django_tables2/utils.py#L289) which allows sth like `A('Alice.Car.Color').resolve(a)`. – user2390182 Sep 10 '18 at 14:53
  • @timgeb, Is `reduce(getitem, ['Alice', 'Car', 'Color'], a)` *not* a slick one-liner? – jpp Sep 10 '18 at 14:54
  • @jpp Well, maybe. :P (It's in the dupe already) – timgeb Sep 10 '18 at 14:55
  • You could also subclass `dict` to allow for this. Change `__getitem__` so it accepts a list (lists are illegal as dict keys), then it recursively calls itself. This is still a recursive approach, but the recursion is hidden an an implementation detail of the class. – Patrick Haugh Sep 10 '18 at 15:00
  • 2
    @David258, I added a [new answer](https://stackoverflow.com/a/52260663/9209546) to the duplicate question. You may find it more Pythonic than the accepted answer. – jpp Sep 10 '18 at 15:05
  • a = {"Alice": {"Car": {"Color": "Blue"}}} key = ["Alice","Car","Color"] result = eval('{}["{}"]["{}"]["{}"]'.format('a',key[0],key[1],key[2])) print(result) – wailinux Sep 10 '18 at 15:14

1 Answers1

0

You can make a function that loops over the keys, indexing the item each time, on the dict with a given list of keys:

def get_nested_value(dct, key_list)
    value = dct 
    for key in key_list:
        value = value[key]

    return value 

keys = ['Alice', 'Car', 'Colour']
print(get_nested_value(a, keys))
N Chauhan
  • 3,407
  • 2
  • 7
  • 21