如何将所有点.
更改为下划线(在dict的键中),给定任意嵌套字典?
我尝试的是编写两个循环,但后来我将仅限于2级嵌套字典。
这......
{
"brown.muffins": 5,
"green.pear": 4,
"delicious.apples": {
"green.apples": 2
{
}
......应该成为:
{
"brown_muffins": 5,
"green_pear": 4,
"delicious_apples": {
"green_apples": 2
{
}
有优雅的方式吗?
答案 0 :(得分:20)
您可以编写递归函数,例如
from collections.abc import Mapping
def rec_key_replace(obj):
if isinstance(obj, Mapping):
return {key.replace('.', '_'): rec_key_replace(val) for key, val in obj.items()}
return obj
当您使用问题中显示的词典调用此词时,您将获得一个新词典,其中键中的点替换为_
s
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
<强>解释强>
这里,我们只检查当前对象是否为dict
的实例,如果是,则我们迭代字典,替换密钥并递归调用该函数。如果它实际上不是字典,那么按原样返回。
答案 1 :(得分:7)
假设.
仅存在于密钥中且所有字典的内容都是原始文字,那么真正便宜的方法是使用str()
或repr()
,进行替换,然后ast.literal_eval()
将其取回:
d ={
"brown.muffins": 5,
"green.pear": 4,
"delicious_apples": {
"green.apples": 2
} # correct brace
}
结果:
>>> import ast
>>> ast.literal_eval(repr(d).replace('.','_'))
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
如果字典在键之外有.
,我们可以通过使用正则表达式来查找'ke.y':
之类的字符串并仅替换那些位来更仔细地替换:
>>> import re
>>> ast.literal_eval(re.sub(r"'(.*?)':", lambda x: x.group(0).replace('.','_'), repr(d)))
{'delicious_apples': {'green_apples': 2}, 'green_pear': 4, 'brown_muffins': 5}
如果你的字典非常复杂,在值和类字典字符串中使用'.'
等等,请使用真正的递归方法。就像我在开始时说的那样,这是便宜的方式。