递归替换字典中的字符

Posted

技术标签:

【中文标题】递归替换字典中的字符【英文标题】:Recursively replace characters in a dictionary 【发布时间】:2016-04-09 11:35:44 【问题描述】:

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

我尝试的是编写两个循环,但是我将被限制为 2 级嵌套字典。

这...


    "brown.muffins": 5,
    "green.pear": 4,
    "delicious.apples": 
        "green.apples": 2
    

...应该变成:


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

有没有优雅的方法?

【问题讨论】:

定义遍历字典键/值的方法,如果键有点,则替换,如果值是另一个字典,则输入递归(调用相同的方法,但现在使用这个字典) 你试过什么?不要用“有两个循环”来“任意嵌套”。 递归之美,宝贝 @PeterWood - 这是任何递归的可能性。如果结构嵌套不是很深,它可能会很好。 @PeterWood 堆栈溢出,宝贝:P 【参考方案1】:

你可以写一个递归函数,像这样

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

【讨论】:

为什么不用dict 而不是Mapping @IronFist 当您检查它是否是dict 的实例时,您将其限制为仅dict 及其子类。取而代之的是,您稍微放宽了条件,并允许任何具有很少方法的类使其看起来像字典。您可能想查看mapping 定义。 请原谅这里缺乏知识..:P .. 还有一件事,这只是建议,你不认为用tr-except 块包装它是安全的,以防止达到最大迭代如果这很重要,并在必要时提出例外或任何针对它的控制措施......? @IronFist 这不是生产就绪代码:D 我不希望任何人按原样使用它。如果他们愿意,他们可以增加递归限制:-)【参考方案2】:

假设. 仅存在于键中并且所有字典的内容都是原始文字,真正便宜的方法是使用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

如果您的字典非常复杂,在值中包含'.' 和类似字典的字符串等,请使用真正的递归方法。不过,就像我一开始所说的那样,这是一种便宜的方式。

【讨论】:

这也将替换值,虽然 @cricket_007 我想他说的是水果和甜点的整数倍。 @erip - 仍然不是 OP 所要求的 假设你没有'my.key': __my_method:P @erip 理想情况下,它也应该对未来的访问者有用,而不仅仅是 OP 的特定情况。不过很有创意

以上是关于递归替换字典中的字符的主要内容,如果未能解决你的问题,请参考以下文章

全排列 (递归求解+字典序) java 转载

递归遍历带有列表的嵌套字典,并替换匹配的值

linux递归替换文件中的字符串

用Python在给定目录及其子目录中递归替换文件中的字符串?

递归查找和替换文件中的字符串,为受影响的文件创建备份

使用grep和sed递归查找和替换所有文件中的字符串[重复]