从嵌套字典中获取键值 Python

3
我有一个包含嵌套字典数据的类。 我需要获取其中所有的键值。 最好的高效方法是什么?
我目前卡在以下代码:
for k,v in data.items():
    print v.keys()

这是数据:

data = {
    "BANK": {
        "no_data": "INT",
    },
    "SHOCK": {
        "drop": "NOTI",
        "rise": "NOTI",
        "high_risk": "ALERT",
    },
    "OFFLINE": {"online": None, "offline_few": "ALERT"},
}

4
请提供预期输出结果。 - Ch3steR
5个回答

3
一种优雅的方法将列表(您的value.keys()列表)连接为一个是使用一个双重循环列表推导式,像这样:
nested_keys = [
    key
    for val in data.values()
    for key in val.keys()]

这将仅获取值字典的键。这不会获取“BANK,SHOCK,OFFLINE”。但是OP的问题不够明确。 - Ch3steR

1
使用生成器:
def all_keys(d):
    for k, v in d.items():
        yield k
        # assume that anything with `items` property will be a mapping
        # this can be replaced with: `isinstance(v, dict)` or `isinstance(v, collections.Mapping)`
        if hasattr(v, 'items'):  
            yield from all_keys(v)

根据您的输入,这将生成:
data = {
    "BANK": {
        "no_data": "INT",
    },
    "SHOCK": {
        "drop": "NOTI",
        "rise": "NOTI",
        "high_risk": "ALERT",
    },
    "OFFLINE": {"online": None, "offline_few": "ALERT"},
}
print(list(all_keys(data)))
# ['BANK', 'no_data', 'SHOCK', 'drop', 'rise', 'high_risk', 'OFFLINE', 'online', 'offline_few']

0
你可以使用一个 NestedDict。首先安装 ndicts
pip install ndicts

那么

from ndicts.ndicts import NestedDict
data = {
    "BANK": {
        "no_data": "INT",
    },
    "SHOCK": {
        "drop": "NOTI",
        "rise": "NOTI",
        "high_risk": "ALERT",
    },
    "OFFLINE": {"online": None, "offline_few": "ALERT"},
}
nd = NestedDict(data)

结果

>>> list(nd.keys())
[('BANK', 'no_data'), ('SHOCK', 'drop'), ('SHOCK', 'rise'), ('SHOCK', 'high_risk'), ('OFFLINE', 'online'), ('OFFLINE', 'offline_few')]

0

递归函数

获取嵌套字典的所有层级中的所有键。

def get_keys(d, result = None): 
  # use default of None to fix issue noted by @Ch3steR
  # namely: http://effbot.org/zone/default-values.htm
  if result is None:
    result = []

  for k, v in d.items():
    if isinstance(v, dict):
        result.append(k)
        get_keys(v, result)
    else:
      result.append(k)

  return result

测试

print(get_keys(data)) 

输出

['BANK', 'no_data', 'SHOCK', 'drop', 'rise', 'high_risk', 'OFFLINE', 'online', 'offline_few']

你会遇到 https://dev59.com/9nNA5IYBdhLWcg3wAItP - Ch3steR
你可以自己检查,运行该函数两次。第一次调用后,get_keys.__defaults__ 将是 (['BANK', 'no_data', 'SHOCK', 'drop', 'rise', 'high_risk', 'OFFLINE', 'online', 'offline_few'],),第二次调用后,get_keys.__defaults__ 将是 (['BANK', 'no_data', 'SHOCK', 'drop', 'rise', 'high_risk', 'OFFLINE', 'online', 'offline_few', 'BANK', 'no_data', 'SHOCK', 'drop', 'rise', 'high_risk', 'OFFLINE', 'online', 'offline_few']) - Ch3steR
@Ch3steR,我的解决方案可能不会有这个问题,请你检查一下? - Piyush Singh
如果您有一个可变的默认参数,请不要直接进行原地修改。只需运行两次或三次,使用 func.__defaults__ 就可以知道了。 - Ch3steR
@PiyushSingh 您的函数出现了与最小惊讶原则和可变默认参数相同的问题。 - Ch3steR
显示剩余2条评论

0
如果您的“实际”键值对都在特定深度,例如深度 1,则可以这样操作:
```html

如果您的“实际”键值对都在特定深度,例如深度 1,则可以这样操作:

```
data = {
    "BANK": {
        "no_data": "INT",
    },
    "SHOCK": {
        "drop": "NOTI",
        "rise": "NOTI",
        "high_risk": "ALERT",
    },
    "OFFLINE": {"online": None, "offline_few": "ALERT"},
}
dic = {k:v for val in data.values() for k,v in val.items()}

但是如果你不知道:

data = {
    "BANK": {
        "no_data": "INT",
    },
    "SHOCK": {
        "drop": "NOTI",
        "rise": "NOTI",
        "high_risk": "ALERT",
    },
    "online": None, 
    "offline_few": "ALERT"
}

在这种情况下,您需要使用递归:
def unnest(dic, final=dict()):
    for key, val in dic.items():
        if not isinstance(val, dict):
            final[key] = val
        else:
            dic2 = dict()
            for k, v in val.items():
                dic2[k] = v
            unnest(dic2, final)
    return final    

dic = unnest(data, {}) #every use of the function should have {} to solve issue pointed by @Ch3steR

无论如何,一旦您拥有“非嵌套”的字典,打印键就是微不足道的事情:
print(dic.keys())

检查你的函数是否会遇到“最小惊讶和可变默认参数”的问题。可以通过检查unnest.__defaults__来确认。 - Ch3steR
@Ch3steR,感谢分享。我不知道Python中存在这样的东西。更新了我的答案以解决问题,我只需要确保每次调用函数时都从一个新的空字典开始。 - Piyush Singh
@Ch3steR,这是一段代码,展示了问题并解决了它: https://repl.it/repls/UselessWorseNewsaggregator - Piyush Singh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接