将所有值的Python Dict展平为True/False
假设我有一个Python dict,它可能包含嵌套到任意级别的其他dict。此外,一些键引用布尔选择,而其他键则不引用。大概是这样的:将所有值的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, '
{'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