0

Apologies if this is really simple, but I can't seem to get it going.

My application is working with nested dicts. For example: -

test = {
    "alpha": "first",
    "beta": {
        "mid": {
            "message": "winner winner"
        }
    },
    "omega": "last"
}

Now I need to be able retrieve values out of that dict using variable the value of which is being dynamically constructed based on myriad other factors. So essentially I'm trying to put together a way to generate the key that I need depending on variable factors.

For example if I get back from one function "beta", from another, "mid" and from another "message", the best I can think to do is assemble a string which looks like the key path.

So for example:

current = '["beta"]["mid"]["message"]'

How can I use current to get back the "winner winner" string?

I have tried things like:-

v = '"[beta"]["mid"]"message]"'
print(test[v])

But just hitting Key errors.

Must be an easy way to get values based on calculated keys. Would appreciate a shove in the right direction.

[Question text updated] Yes, I know I can do:

val = test['beta']['mid']['message'] 

And get back the value, I'm stuck on how to use the generated string as the the key path. Apologies for not being clear enough.

Indrid
  • 962
  • 4
  • 25
  • 39

4 Answers4

3
import re

t = '["beta"]["mid"]["message"]'
val = None
for i in re.findall(r'"([^"]+)"', t):
    if(val == None):
        val = test.get(i)
    else:
        val = val.get(i)
print(val)

or,

from functools import reduce
import operator
import re

t = '["beta"]["mid"]["message"]'
reduce(operator.getitem, re.findall(r'"([^"]+)"', t), test)
winner winner
Epsi95
  • 8,832
  • 1
  • 16
  • 34
1
current = '["beta"]["mid"]["message"]'
keys = [w.strip('[]"') for w in current.split('"]["')]
test[keys[0]][keys[1]][keys[2]]

# or
# key_one = keys[0]
# key_two = keys[1]
# key_three = keys[2]
# v = test[key_one][key_two][key_three]    
Naivre
  • 97
  • 7
  • My apologies, I was not clear enough. I have updated the question. – Indrid Feb 06 '21 at 15:01
  • @Indrid, it's not clear if your have the original keys like a mixed string or like isolated keys. – Naivre Feb 06 '21 at 15:23
  • Mixed string generated once path is calculated. My issue was how to use that string to collect the value from the dict. I’m working around it by using single vars in the path [ ] placeholders. Would have been good to be able to use the full string variable. – Indrid Feb 07 '21 at 16:11
  • So using `split` and `strip` (my two first lines) combination you can do that! @Indrid – Naivre Feb 07 '21 at 16:17
  • You are correct, I never appreciated the subtlety in that method till I re-examined it. I like it very much and have upvoted it. I'll definitely take note of that technique for the future! – Indrid Feb 07 '21 at 19:41
1

Store the three keys as three different variables rather than as a string:

key_one = 'beta'
key_two = 'mid'
key_three = 'message'

v = test[key_one][key_two][key_three]

If you already have the keys in the string format you describe, then do some string splitting to produce three variables like the above. You don't want to eval the code as it creates a security risk.

D Hudson
  • 1,004
  • 5
  • 12
  • Thank you! Yes, this works. I can work with this. Agree about eval. I wonder if keys have a 'type' and whether a string could be coerced to that type and thus applied as a single nested chunk, – Indrid Feb 06 '21 at 15:03
0

This should do it:

v = test['beta']['mid']['message']
print(v)

Note: The issue is you're indexing the dictionary with a string in your example, not a set of keys.

William Baker Morrison
  • 1,642
  • 4
  • 21
  • 33