Home > Blockchain >  Using a string as a dictionary's index
Using a string as a dictionary's index

Time:09-06

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
  • Related