Python 递归地替换字典中的字符

Python 递归地替换字典中的字符,python,string,dictionary,recursion,Python,String,Dictionary,Recursion,如果给定一个任意嵌套的字典,如何将所有点更改为下划线(在dict的键中) 我试着写两个循环,但是我只能使用两级嵌套字典 这个 { "brown.muffins": 5, "green.pear": 4, "delicious.apples": { "green.apples": 2 { } 。。。应成为: { "brown_muffins": 5, "green_pear": 4, "delicious_apples":

如果给定一个任意嵌套的字典,如何将所有点
更改为下划线(在dict的键中)

我试着写两个循环,但是我只能使用两级嵌套字典

这个

{
    "brown.muffins": 5,
    "green.pear": 4,
    "delicious.apples": {
        "green.apples": 2
    {
}
。。。应成为:

{
    "brown_muffins": 5,
    "green_pear": 4,
    "delicious_apples": {
        "green_apples": 2
    {
}

有一种优雅的方法吗?

您可以编写一个递归函数,如下所示

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的实例,如果是,则迭代字典,替换键并递归调用函数。如果它实际上不是字典,则按原样返回。

假设
仅存在于键中,并且字典的所有内容都是原始文本,真正便宜的方法是使用
str()
repr()
,进行替换,然后
ast.literal\u 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}

如果您的字典非常复杂,在值和类似字典的字符串中有
,等等,请使用真正的递归方法。正如我在开始时所说的,这是一种廉价的方法。

定义循环字典键/值的方法,如果键有点,则替换,如果值是另一个dict,则输入递归(调用相同的方法,但现在使用此dict)您尝试了什么?不要用“有两个循环”来表示“任意嵌套”。递归的美妙之处,baby@PeterWood-这是任何递归的可能性。如果结构嵌套得不是很深,它可能会很好。@PeterWood stack overflow,baby:p这也会在值中替换,though@cricket_007我想他说的是水果和糖果的整数。@erip-仍然不是OP问的,假设你没有
{'my.key':\uu my\u method}
:P@erip理想的,它也应该对未来的访客有用,而不仅仅是针对具体的案例。非常有创意。为什么不使用
dict
而不是
Mapping
。相反,您可以稍微放宽条件,允许任何具有少量方法的类,使其看起来像字典。你可能想看看定义。请原谅我在这里缺乏知识。。还有一件事,这只是一个建议,你不认为用
tr来包装它是安全的吗?除非
块可以避免达到最大迭代次数(如果这很重要),并在达到最大迭代次数时引发一个异常,或者对其采取任何控制措施…?@IronFist这不是生产就绪代码:D我不希望任何人按原样使用它。如果愿意,可以增加递归限制:-)