将所有值的 Python 字典展平到 True/False

Flatten Python Dict for All Values Down to True/False

假设我有一个 Python 字典,它可能包含嵌套到任意级别的其他字典。此外,一些键引用布尔值选择,而其他键则不引用。像这样:

{'Key1': 'none',
 'Key2': {'Key2a': True, 'Key2b': False},
 'Key3': {'Key3a': {'Key3a1': 'some', 'Key3a2': 'many'}, 'Key3b': True}}

我想做的是把它变成这样:

{'Key1_none': 1,
 'Key2_Key2a': 1,
 'Key2_Key2b': 0,
 'Key3_Key3a_Key3a1_some': 1,
 'Key3_Key3a_Key3a2_many': 1,
 'Key3b': 1}

现在只有 dict 变平了,所有的键现在都有布尔值答案。 This solution 是一个很好的开始,但我对 Python 不是很熟悉。我链接到的解决方案处理了大多数情况,但它并没有在所有情况下都深入到价值级别。对于上面的示例,它会将第一部分保留为:

{'Key1': 'none',
 'Key2_Key2a': 1,
 'Key2_Key2b': 0,
 ...}

显然用 1/0 替换 True/False 是微不足道的。我的问题更多是关于当键的值不是 True 或 False 时如何扁平化到附加级别。

我认为这个递归函数应该可以做到:

def flatten(d, prefix=''):
    prefix = prefix + '_' if prefix else ''
    new = {}
    for k, v in d.items():
        if isinstance(v, bool):
            new[prefix + k] = int(v)
        elif isinstance(v, dict):
            new.update(flatten(v, prefix=prefix + k))
        elif isinstance(v, basestring):  # python3 -- str
            new[prefix + k + '_' + v] = 1
        else:
            raise TypeError('Unknown item type.')
    return new

如果值是一个字典,并且键的 "prefix" 附加到嵌套前缀的任何前一层,就会发生递归。

当然,您可以通过在 isinstance 检查中使用适当的 ABC 来做得更好...例如

bool -> numbers.Integral
dict -> collections.Mapping

另一种解决方案,基于solution you're provided

import collections

def flatten(d, parent_key='', sep='_'):
    items = []
    for k, v in d.items():
        new_key = parent_key + sep + k if parent_key else k
        if isinstance(v, collections.MutableMapping):
            items.extend(flatten(v, new_key, sep=sep).items())
        else:
            if isinstance(v, bool):
                items.append((new_key, int(v)))
            else:
                items.append((new_key, 1))
    return dict(items