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.

2
  • 2
    eval('test' + '["beta"]["mid"]["message"]') but there should be security risk Commented Feb 6, 2021 at 14:53
  • Works great though! Commented Feb 6, 2021 at 15:11

4 Answers 4

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
Sign up to request clarification or add additional context in comments.

Comments

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.

1 Comment

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,
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]    

5 Comments

My apologies, I was not clear enough. I have updated the question.
@Indrid, it's not clear if your have the original keys like a mixed string or like isolated keys.
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.
So using split and strip (my two first lines) combination you can do that! @Indrid
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!
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.

1 Comment

My apologies, I was not clear enough. I have updated the question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.