从嵌套字典python获取键值

时间:2020-04-09 11:56:59

标签: python dictionary nested

我有一个带有嵌套字典数据对象的类。我需要从中获取所有关键值。最好的有效方法是什么?

我坚持以下几点:

 protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        var dateOfBirth = (DateTime)value;

        var currentDate = DateTime.UtcNow;

        var minimumAge = new DateTime(currentDate.Year - 17, currentDate.Month, currentDate.Day, currentDate.Hour, currentDate.Minute, currentDate.Second);
        var maximumAge = new DateTime(currentDate.Year - 34, currentDate.Month, currentDate.Day, currentDate.Hour, currentDate.Minute, currentDate.Second);

        var isTooYoung = dateOfBirth > minimumAge;
        var isTooOld = dateOfBirth < maximumAge;

        if (isTooYoung || isTooOld) 
        {
            // it is about this line
            var localizer = (ILocalizer)validationContext.GetService(typeof(ILocalizer));
            var error = localizer.GetString(ErrorMessageString);
            return new ValidationResult(error);
        } 

        return ValidationResult.Success;
    }

这是数据:

for k,v in data.items():
    print v.keys()

4 个答案:

答案 0 :(得分:3)

将列表(您的value.keys()列表)连接为一个优雅的方法是使用双循环列表理解,如下所示:

nested_keys = [
    key
    for val in data.values()
    for key in val.keys()]

答案 1 :(得分: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']

答案 2 :(得分: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']

答案 3 :(得分:0)

如果所有“实际”键值对都位于某个深度(例如深度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())