Adrian Vulpeanu
Adrian Vulpeanu

Reputation: 73

How to get a python dict value by using in his key in a dict within other dicts

Some one know if its possible to get a dict inside a dict by using their keys as strings... Sorry for the bad explation i think the code would be more clear... don't know how to properly say this

s={"framework": {"challenger": {
    "logo.qvg": "50c137c8199d0a807bc31b5c384e67d6c1c0837061bd7d39ed15943b"}}}

possible_folders=["tractor","svg","framework","common",'framework["challenger"]']

print(s['framework']['challenger'])  # this line is working

print(s[possible_folders[-1]])   # here im getting keyerror-> due to the string... 

Upvotes: 1

Views: 83

Answers (5)

Alex Gertsovich
Alex Gertsovich

Reputation: 89

First of all I strongly suggest reading this - I would go that way. Having said that, below you will find the non-responsible way (using eval) of achieving this. Again, strongly suggest going that way.

possible_folders=["tractor","svg","framework","common","['framework']['challenger']"]
print(eval('s'+possible_folders[-1]))

Upvotes: -1

Tharun N
Tharun N

Reputation: 11

I agree with the above answers, because they're how you do it in a good programming way. Although I have a quick fix to make your exact command work, but it is NOT a good programming way, since it uses hardcoding and also eval function.

In the first line, you are accessing with print(s['framework']['challenger']), but in second line, you are accessing like s['framework["challenger"]' (see the brackets).

You can change the possible folders from

possible_folders=["tractor","svg","framework","common",'framework["challenger"]']

to

possible_folders=["tractor","svg","framework","common",'["framework"]["challenger"]']
eval("s"+possible_folders[-1])

Upvotes: -1

FloLie
FloLie

Reputation: 1841

You can use the eval() function like:

s={"framework": {"challenger": {
    "logo.qvg": "50c137c8199d0a807bc31b5c384e67d6c1c0837061bd7d39ed15943b"}}}

possible_folders=["tractor","svg","framework","common",'framework["challenger"]']


def get_entry(d, k):
    
    eval_string = "d" +"".join([".get('" + i.replace('"',"").replace("[","").replace("]","") + "')" for i in k.split("[")])
    return eval(eval_string)
get_entry(s,possible_folders[-1])
Out[32]: {'logo.qvg': '50c137c8199d0a807bc31b5c384e67d6c1c0837061bd7d39ed15943b'}

I am not saying I would recommend it, but it is the only solution that works with the String Syntax in your questions. The other answers are better, however require a change in your list

Upvotes: -1

Iguananaut
Iguananaut

Reputation: 23376

I think what you want is a way to access nested dicts by a sequence of keys. There are many ways to do this. One I like is to define a simple function like:

def nested_get(d, *keys, *, default=None):
    for k in keys:
        try:
            d = d[k]
        except KeyError:
            return default

    return d

Then use a tuple like keys = ('framework', 'challenger'):

nested_get(d, *keys)

Upvotes: 3

chepner
chepner

Reputation: 532428

It's not possible. s is a dict with a single key, "framework". There is no way to index s to get something deeper inside one of s's values.

You can write a function that takes a list of keys and iteratively digs into the dict, however. (Iguananaut does this with better error handling.)

def chain_lookup(s, *keys):
    d = s
    for key in keys:
        d = d[key]
    return d


result = chain_lookup(s, "framework", "challenger")
# result == {"logo.qvg": "..."}

Upvotes: 3

Related Questions