I have a large dictionary (originally a json), something like this:
dictionary = {
"Thing1": {
"Thing1.1": {
"Thing1.1.1": "Text",
"Thing1.1.2": "Text",
"Thing1.1.3": "Text"},
"Thing1.2": {
"Thing1.2.1": "Text",
"Thing1.2.2": "Text",
"Thing1.2.3": "Text we're interested in"},
"Thing1.3": {
"Thing1.3.1": "Text",
"Thing1.3.2": "Text",
"Thing1.3.3": "Text"}
},
"Thing2": {
"Thing2.1": {
"Thing2.1.1": "Text",
"Thing2.1.2": "Text",
"Thing2.1.3": "Text"},
"Thing2.2": {
"Thing2.2.1": "Text",
"Thing2.2.2": "Text",
"Thing2.2.3": "Text"},
"Thing2.3": {
"Thing2.3.1": "Text",
"Thing2.3.2": "Text",
"Thing2.3.3": "Text"}
},
"Thing3": {
"Thing3.1": {
"Thing3.1.1": "Text",
"Thing3.1.2": "Text",
"Thing3.1.3": "Text"},
"Thing3.2": {
"Thing3.2.1": "Text",
"Thing3.2.2": "Text",
"Thing3.2.3": "Text"},
"Thing3.3": {
"Thing3.3.1": "Text",
"Thing3.3.2": "Text",
"Thing3.3.3": "Text"}
}
}
And, having automated some things, I have some keys that are interesting in a string, as such:
key1 = '["Thing1"]["Thing1.2"]["Thing1.2.3"]'
and I'd like to be able to call the value for which I have the key as if it was the following:
value = dictionary["Thing1"]["Thing1.2"]["Thing1.2.3"]
I have tried using exec, and formatting everything neatly using f-strings, however that's horrible and it does give me some trouble of its own.
CodePudding user response:
If you want to give "1.2.3"
and get the item you want from the list you can use this code:
keys = "1.2.3".split(".")
value = dictionary["Thing" keys[0]]["Thing" keys[0] "." keys[1]]["Thing" keys[0] "." keys[1] "." keys[2]]
If you want, you can get it from your key1
variable:
key1 = '["Thing1"]["Thing1.2"]["Thing1.2.3"]'
keys = key1[key1.rfind("Thing") 5: -2].split(".")
value = dictionary["Thing" keys[0]]["Thing" keys[0] "." keys[1]]["Thing" keys[0] "." keys[1] "." keys[2]]
CodePudding user response:
As I understand the question, you will always receive the three keys in a string as you showed above, if not please correct me. In that case, I have find the following solution:
text = '["Thing1"]["Thing1.2"]["Thing1.2.3"]'
keys = [eval(i) for i in text.replace("[", "").split("]")[:-1]]
target = dictionary[keys[0]][keys[1]][keys[2]]
Being the variables:
keys = ['Thing1', 'Thing1.2', 'Thing1.2.3']
target = "Text we're interested in"
Edit: You can also do this if you don´t want to use exec or eval:
keys = text.replace("[", "").replace('"', "").split("]")[:-1]
target = dictionary[keys[0]][keys[1]][keys[2]]
If u have a variable depth, you can replace the last lines with:
target = dictionary
for k in keys:
target = target[k]
CodePudding user response:
Let's assume that the depth of the nested dictionaries is unknown. In that case we need a loop to navigate it. You can use a regular expression to isolate the embedded keys. Something like this:
import re
dictionary = {
"Thing1": {
"Thing1.1": {
"Thing1.1.1": "Text",
"Thing1.1.2": "Text",
"Thing1.1.3": "Text"},
"Thing1.2": {
"Thing1.2.1": "Text",
"Thing1.2.2": "Text",
"Thing1.2.3": "Text we're interested in"},
"Thing1.3": {
"Thing1.3.1": "Text",
"Thing1.3.2": "Text",
"Thing1.3.3": "Text"}
},
"Thing2": {
"Thing2.1": {
"Thing2.1.1": "Text",
"Thing2.1.2": "Text",
"Thing2.1.3": "Text"},
"Thing2.2": {
"Thing2.2.1": "Text",
"Thing2.2.2": "Text",
"Thing2.2.3": "Text"},
"Thing2.3": {
"Thing2.3.1": "Text",
"Thing2.3.2": "Text",
"Thing2.3.3": "Text"}
},
"Thing3": {
"Thing3.1": {
"Thing3.1.1": "Text",
"Thing3.1.2": "Text",
"Thing3.1.3": "Text"},
"Thing3.2": {
"Thing3.2.1": "Text",
"Thing3.2.2": "Text",
"Thing3.2.3": "Text"},
"Thing3.3": {
"Thing3.3.1": "Text",
"Thing3.3.2": "Text",
"Thing3.3.3": "Text"}
}
}
key = '["Thing1"]["Thing1.2"]["Thing1.2.3"]'
list_ = re.findall(r'\"(.*?)\"', key)
d = dictionary
for k in list_:
if (d := d.get(k)) is None:
break
print(d)
Output:
Text we're interested in