Python 字典使用第二个字典替换值(但搜索值而不是整个值)

Python 字典使用第二个字典替换值(但搜索值而不是整个值),python,Python,我试图用dict中的另一个值替换dict中的一个值。从我的搜索中已经做了很多,但我认为我有一个独特的情况,因为我需要搜索一个值的值,而不是替换整个值 到目前为止,我已经尝试过这一方法,并且部分有效: input_data = [ { "name": "system1", "other_param": "%param1%", "secret_text&q

我试图用dict中的另一个值替换dict中的一个值。从我的搜索中已经做了很多,但我认为我有一个独特的情况,因为我需要搜索一个值的值,而不是替换整个值

到目前为止,我已经尝试过这一方法,并且部分有效:

input_data = [
    {
        "name": "system1",
        "other_param": "%param1%",
        "secret_text": "%secret%",
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"%max_date%\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }
    }
]

variables = {
    '%secret%': "abc",
    '%param1%': "text_param",
    '%max_date%': '2018-01-01'
}

def process_variables(dict_obj, dict_vars):
    for k, v in dict_obj.items():
        for var, val in dict_vars.items():
            dict_obj[k] = str(v).replace(var, val)

    return dict_obj


for x in input_data:
    print(process_variables(x, variables))
预期的结果是:

{
    "name": "system1",
    "other_param": "text_param",
    "secret_text": "abc",
    "options": {
        "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
    }
}
实际结果:

{
   "name":"system1",
   "other_param":"%param1%",
   "secret_text":"%secret%",
   "options":"{\\'conditions\\': \\'[\"f--updated_at,geq,\\\\\"2018-01-01\\\\\"\",\"f--status,eq,\\\\\"Void\\\\\"\"]\\'}"
}
正如您所看到的,它似乎将dict向下展平,而不是替换顶级值


有没有更好的方法来实现这一点?如果需要,我可以更改JSON输入,但我需要进行某种变量替换,因为我有数百个输入,这些输入都是我计划迭代的公共值。

我能够将输入数据视为字符串并使用ast(抽象语法树)来获得结果:

输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

[{'name':'system1','other_param':'text_param','secret_text':'abc','options':{'conditions':'['f--updated_at,geq,\\\\'2018-01-01\\\','f--status,eq,\\\\\\\'Void\\\\\\\\\']}]

我不能保证这是最好的方法,但它简化了过程。值得一试吗?

我能够将输入数据作为字符串处理并使用ast(抽象语法树)实现以下结果:

输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

[{'name':'system1','other_param':'text_param','secret_text':'abc','options':{'conditions':'['f--updated_at,geq,\\\\'2018-01-01\\\','f--status,eq,\\\\\\\'Void\\\\\\\\\']}]

我不能保证这是最好的方法,但它简化了过程。值得一试吗?

您可以递归地循环
输入\u数据
,并分别替换每个值。递归循环的好处是,您无需关心
input\u数据
嵌套的深度:

def traverse_dict(dct, replacements):
    if isinstance(dct, list):
        for i, item in enumerate(dct):
            dct[i] = traverse_dict(item, variables)
    elif isinstance(dct, dict):
        for k, v in dct.items():
            dct[k] = traverse_dict(v, variables)
    else:
        # all values in the JSON end up here
        if isinstance(dct, str):
            for repl in replacements:
                if repl in dct:
                    dct = dct.replace(repl, replacements[repl])
        return dct
    return dct

result = traverse_dict(input_data, variables)
print(result)
输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

使
输入\u数据
更加复杂,仍能正确替换:

input_data = [
    {
        "name": "system1",
        "other_param": "%param1%",
        "secret_text": "%secret%",
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"%max_date%\\\"\",\"f--status,eq,\\\"Void\\\"\"]",
            "foo": [
                {
                    "bar": {
                        "baz": "%secret%",
                    }
                }
            ]
        }
    }
]
输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

您可以递归地循环输入数据,并分别替换每个值。递归循环的好处是,您无需关心
input\u数据
嵌套的深度:

def traverse_dict(dct, replacements):
    if isinstance(dct, list):
        for i, item in enumerate(dct):
            dct[i] = traverse_dict(item, variables)
    elif isinstance(dct, dict):
        for k, v in dct.items():
            dct[k] = traverse_dict(v, variables)
    else:
        # all values in the JSON end up here
        if isinstance(dct, str):
            for repl in replacements:
                if repl in dct:
                    dct = dct.replace(repl, replacements[repl])
        return dct
    return dct

result = traverse_dict(input_data, variables)
print(result)
输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

使
输入\u数据
更加复杂,仍能正确替换:

input_data = [
    {
        "name": "system1",
        "other_param": "%param1%",
        "secret_text": "%secret%",
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"%max_date%\\\"\",\"f--status,eq,\\\"Void\\\"\"]",
            "foo": [
                {
                    "bar": {
                        "baz": "%secret%",
                    }
                }
            ]
        }
    }
]
输出:

<class 'list'>
[{'name': 'system1', 'other_param': 'text_param', 'secret_text': 'abc', 'options': {'conditions': '["f--updated_at,geq,\\"2018-01-01\\"","f--status,eq,\\"Void\\""]'}}]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]"
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]
[
    {
        "name": "system1", 
        "options": {
            "conditions": "[\"f--updated_at,geq,\\\"2018-01-01\\\"\",\"f--status,eq,\\\"Void\\\"\"]", 
            "foo": [
                {
                    "bar": {
                        "baz": "abc"
                    }
                }
            ]
        }, 
        "other_param": "text_param", 
        "secret_text": "abc"
    }
]

您正在将“[\”转换为字符串(
str(v).replace(var,val)
),这就是输出混乱的原因。您正在将“[\”转换为字符串(
str(v).replace(var,val)
),这就是输出混乱的原因。谢谢。如果键或任何东西恰好被命名为值,那么它会比ast建议安全一点。谢谢。如果键或任何东西恰好被命名为值,那么它会比ast建议安全一点。谢谢e如果键/值匹配,则使用其他答案。我不想替换它们。当然..没问题谢谢。如果键/值匹配,则使用其他答案。我不想替换它们。当然..没问题