简体   繁体   中英

Extracting values from Dictionary of lists with nested dictionaries

EDIT: I modified what the code I previously wrote because the names of the keys are the same in the list of dictionaries.

I currently have to work with a nested dictionary that has this form:

r = {'keyX': [{'keyAa': valueAa,
               'keyAb': valueAb,
               'keyAc': {'keyAca': {'keyAcaa': valueAcaa
                                    'keyAcab': valueAcab
                                    'keyAcac': valueAcac
                                     ...}}
               'keyAd': valueAd
               'keyAe': valueAe 
              }
              {'keyAa': valueBa,
               'keyAb': valueBb,
               'keyAc': {'keyAca': {'keyAcaa': valueBcaa
                                    'keyAcab': valueBcab
                                    'keyAcac': valueBcac
                                     ...}}
               'keyAd': valueBd
               'keyAe': valueBe 
              }
              ...
             ]
    'keyY': {'key1a': value1a
             'key1b': value1b
             ...}}

I want to find the maximum value for keyAcac. (name of the key is the same for different dictionaries) To get the maximum I tried to use int() before the max() function:

max_volume = max(int(r['keyX']['keyAc']['keyAca']['KeyAcac'])))

or:

max_volume = max(int(r['keyX']['keyAc']['keyAca']['KeyAcac']) for a in a.values())

to do this in various ways but I always get the "TypeError: list indices must be integers or slices, not str" Error, and i cant't go over this problem. Could you help me?

Once found this maximum value I would also like to return all the dictionary with keys and values with the same main letter. (Example: if the maximum value is valueBcac, I would like to have as output keyBa, keyBb, keyBc,..., with all their values). Is this possible?

Yup, you could use a recursive generator function to walk through the nested structure, yielding "paths". Your original example has lists as well as dicts, and this also takes care of any possible sets (in a way, anyway).

After that, you can simply use the built-in max() function with that iterator.

r = {
    "keyX": [
        {
            "keyAa": 123,
            "keyAb": 543,
            "keyAc": {
                "keyAca": {
                    "keyAcaa": 635,
                    "keyAcab": 234,
                    "keyAcac": 753,
                }
            },
            "keyAd": 5753,
            "keyAe": 12312,
        },
        {
            "keyBa": 642,
            "keyBb": 753,
            "keyBc": {
                "keyBca": {
                    "keyBcaa": 25472,
                    "keyBcab": 75311,
                    "keyBcac": 23432,
                }
            },
            "keyBd": 2362,
            "keyBe": 742,
        },
    ],
    "keyY": {"key1a": 12321, "key1b": 66421},
}


def iterate_nested(s, path=()):
    if isinstance(s, (list, tuple)):
        for index, value in enumerate(s):
            yield from iterate_nested(value, path + (index,))
    elif isinstance(s, dict):
        for key, value in s.items():
            yield from iterate_nested(value, path + (key,))
    elif isinstance(s, set):
        for value in s:
            # just mark that it's some set item with `set`
            yield from iterate_nested(value, path + (set,))
    else:
        yield (path, s)

# For debugging:
for path, value in iterate_nested(r):
    print(path, value)

# For the actual problem:
highest_value_and_path = max(
    iterate_nested(r), key=lambda pair: pair[1]
)
print("Highest:", highest_value_and_path)

The output is eg

~/Desktop $ python3 so63882758.py
('keyX', 0, 'keyAa') 123
('keyX', 0, 'keyAb') 543
('keyX', 0, 'keyAc', 'keyAca', 'keyAcaa') 635
('keyX', 0, 'keyAc', 'keyAca', 'keyAcab') 234
('keyX', 0, 'keyAc', 'keyAca', 'keyAcac') 753
('keyX', 0, 'keyAd') 5753
('keyX', 0, 'keyAe') 12312
('keyX', 1, 'keyBa') 642
('keyX', 1, 'keyBb') 753
('keyX', 1, 'keyBc', 'keyBca', 'keyBcaa') 25472
('keyX', 1, 'keyBc', 'keyBca', 'keyBcab') 75311
('keyX', 1, 'keyBc', 'keyBca', 'keyBcac') 23432
('keyX', 1, 'keyBd') 2362
('keyX', 1, 'keyBe') 742
('keyY', 'key1a') 12321
('keyY', 'key1b') 66421
Highest: (('keyX', 1, 'keyBc', 'keyBca', 'keyBcab'), 75311)

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