递归替换字典中的字符

时间:2016-01-05 15:21:16

标签: python string dictionary recursion

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

我尝试的是编写两个循环,但后来我将仅限于2级嵌套字典。

这......

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

......应该成为:

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

有优雅的方式吗?

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}

如果你的字典非常复杂,在值和类字典字符串中使用'.'等等,请使用真正的递归方法。就像我在开始时说的那样,这是便宜的方式。