简体   繁体   中英

Pythonic way to find the key associated with nested dictionary

I have a dictionary where each key has a dictionary as its value (the nested dictionaries all have the same set of keys). I'm trying to find the key associated with two conditions on subkeys: the max value of a subkey given another subkey is True.

For example:

d = {'key1' : {'subkey1' : True,  'subkey2' : 4},
     'key2' : {'subkey1' : True,  'subkey2' : 8},
     'key3' : {'subkey1' : False, 'subkey2' : 1},
     'key4' : {'subkey1' : False, 'subkey2' : 9} }

I would want the result to be 'key2' because it is the max value of 'subkey2' where 'subkey1' is True.

My temptation is to put everything into an array and find the indexes associated with these values, but I have the impression this can be accomplished without adding more variables to store the same information. I thought there might be a better way since I'm relatively new to Python.

Any suggestions? Thanks!

This is an optional implementation to your issue.

First, filter all subkey1 with True.

Second, find from the filtered dictionary the max value within subkey2.

d = {'key1' : {'subkey1' : True,  'subkey2' : 4},
     'key2' : {'subkey1' : True,  'subkey2' : 8},
     'key3' : {'subkey1' : False, 'subkey2' : 1},
     'key4' : {'subkey1' : False, 'subkey2' : 9} }

max_d = {v["subkey2"]:{k:v} for k,v in d.items() if v["subkey1"]} # create new dictionary that the key is the value from subkey2 and the value is the original key and value.
max_int = max(max_d.keys(), key=int) # get the max key

print (max_d[max_int]) # print the maximum 

>>> {'key2': {'subkey1': True, 'subkey2': 8}}

It's a bit convoluted but how about this:

print(d[max({key:d[key] for key in [k for k in d.keys() if d[k]['subkey1'] is True]})])

First we make a list of main keys that have subkey1 as True, then for each of them we rebuild a dictionary of key value pairs and we take the key with the max value

Haven't fully tested this so please do at your end if you consider it worth the time.

What you might need is reduce from functools

Here is the solution you might be looking for:

from functools import reduce
import operator

d = {'key1' : {'subkey1' : True,  'subkey2' : 4},
     'key2' : {'subkey1' : True,  'subkey2' : 8},
     'key3' : {'subkey1' : False, 'subkey2' : 1},
     'key4' : {'subkey1' : False, 'subkey2' : 9} }
maxsum=0
for k in d:
    if reduce(operator.getitem, [k,'subkey1'], d):
        value = (reduce(operator.getitem, [k,'subkey2'], d))
        if maxsum<value:
            maxsum=value
print(maxsum)

Basically what this reduce(operator.getitem, [k,'subkey1'], d) does is it takes values from the sub dictionary. For example:

d = {'John' : {'Male' : True,  'age' : 41}}
reduce(operator.getitem, ['John','Male'], d)

output:

True

Here reduce traverses through John-->Male and gets the result as True

We can also give lists as argument. Take a look at this,

from functools import reduce
import operator

d = {'John' : {'Male' : True,  'age' : 41},
         'Vishnu':{'Male':True ,'age':23}}
chklist1 = ['John','Male']
chklist2 = ['Vishnu','age']
print(reduce(operator.getitem, chklist1, d))
print(reduce(operator.getitem, chklist2, d))

output:

True
23

You can't always expect the dict to be a dict of dict. It can be say a dict of a dict of a dict of a dict. (Who knows? things happen!)

from functools import reduce
import operator

d = {
    "John":{
        "Age": 23,
        "Sex": 'M',
        "Country": 'USA'
        },
    "Vishnu":{
        "Age": 1,
        "Country": {
            "India": 'TamilNadu',
            "USA": None,
            "South Africa": None
        }
        }
}
chklist1 = ['John','Age']
chklist2 = ['Vishnu','Country','India']
print(reduce(operator.getitem, chklist1, d))
print(reduce(operator.getitem, chklist2, d))

output:

23
TamilNadu

So now coming back to your problem:

for k in d:
    if reduce(operator.getitem, [k,'subkey1'], d):
        value = (reduce(operator.getitem, [k,'subkey2'], d))
        if maxsum<value:
            maxsum=value
print(maxsum)

For every key k which would be your key1,key2,... and so on. First reduce(operator.getitem, [k,'subkey1'], d) checks if the value contained within it is True or False . Only proceeds if it is True

Then maxsum is set to the second item in sub_dict of dict. For every key it is checked and if another value greater than the current one is found the value is changed else it goes on. Until you find the maximum value which you can print out.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM