将所有值的 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
假设我有一个 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