Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/python-2.7/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将所有值的Python Dict展平为True/False_Python_Python 2.7_Dictionary - Fatal编程技术网

将所有值的Python Dict展平为True/False

将所有值的Python Dict展平为True/False,python,python-2.7,dictionary,Python,Python 2.7,Dictionary,假设我有一个Python dict,它可能包含嵌套到任意级别的其他dict。此外,一些键引用布尔选择,而其他键则不引用。大概是这样的: {'Key1': 'none', 'Key2': {'Key2a': True, 'Key2b': False}, 'Key3': {'Key3a': {'Key3a1': 'some', 'Key3a2': 'many'}, 'Key3b': True}} 我想做的是将其转化为: {'Key1_none': 1, 'Key2_Key2a': 1, '

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

{'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被展平,所有键现在都有布尔答案。这是一个很好的开始,但我对Python不太熟悉。我链接到的解决方案处理大多数情况,但并不是在所有情况下都深入到值级别。在上面的例子中,它将第一部分保留为:

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

显然,用1/0替换真/假是微不足道的。我的问题更多的是当键的值不是真或假时,如何降低到附加级别。

我认为这个递归函数应该做到这一点:

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
如果值是dict,并且键的“前缀”被附加到嵌套的前一级前缀上,则会发生递归

当然,在
isinstance
检查中使用适当的ABC可以做得更好。。。e、 g

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

还有一个解决方案,基于


谢谢我很好奇你用
#python3--str
评论的那行。我正在使用Python 2.7。你在这里指的是什么?在python2.x上有两种不同的字符串类型(
str
unicode
),它们都是从
basestring
继承的,因此
isinstance
检查将通过
str
unicode
对象。在python3.x上,类型
unicode
消失(有点…),所有字符串的行为都类似于python2.x的
unicode
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