从带有嵌套字典的列表字典中提取值

时间:2020-09-14 10:46:05

标签: python python-3.x list dictionary nested

编辑: 我修改了我以前编写的代码,因为键名在字典列表中是相同的。

我目前必须使用具有以下形式的嵌套字典:

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
             ...}}

我想找到keyAcac的最大值。 (不同字典的键名相同) 为了获得最大值,我尝试在max()函数之前使用int():

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

或:

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

以各种方式执行此操作,但我总是收到“ TypeError:列表索引必须是整数或切片,而不是str”错误,并且我无法解决此问题。你能帮我吗?

一旦找到这个最大值,我也想返回所有带有相同主键的键和值的字典。 (示例:如果最大值为valueBcac,我希望将所有值都作为keyBa,keyBb,keyBc,...作为输出)。这可能吗?

1 个答案:

答案 0 :(得分:1)

是的,您可以使用递归生成器函数遍历嵌套结构,从而产生“路径”。您最初的示例包含列表和字典,并且还处理了所有可能的集合(无论如何以某种方式)。

在那之后,您只需在该迭代器中使用内置的max()函数即可。

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)

输出例如

~/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)