简体   繁体   English

Python:替换嵌套字典中的值

[英]Python: Replace values in nested dictionary

I want to replace the values (formated as strings) with the same values as integers , whenever the key is ' current_values '.每当键为“ current_values ”时,我想用与integers相同的值替换值(格式为字符串)。

d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}

Desired Output:所需 Output:

d = {'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}

The following piece of code replaces (substrings of) values in a dictionary.以下代码替换字典中的(子字符串)值。 It works for nested json structures and copes with json, list and string types.它适用于嵌套的 json 结构并处理 json、列表和字符串类型。 You can add other types if needed.如果需要,您可以添加其他类型。

def dict_replace_value(d, old, new):
    x = {}
    for k, v in d.items():
        if isinstance(v, dict):
            v = dict_replace_value(v, old, new)
        elif isinstance(v, list):
            v = list_replace_value(v, old, new)
        elif isinstance(v, str):
            v = v.replace(old, new)
        x[k] = v
    return x


def list_replace_value(l, old, new):
    x = []
    for e in l:
        if isinstance(e, list):
            e = list_replace_value(e, old, new)
        elif isinstance(e, dict):
            e = dict_replace_value(e, old, new)
        elif isinstance(e, str):
            e = e.replace(old, new)
        x.append(e)
    return x

# See input and output below
b = dict_replace_value(a, 'string', 'something')

Input:输入:

a = {
    'key1': 'a string',
    'key2': 'another string',
    'key3': [
        'a string',
        'another string',
        [1, 2, 3],
        {
            'key1': 'a string',
            'key2': 'another string'
        }
    ],
    'key4': {
        'key1': 'a string',
        'key2': 'another string',
        'key3': [
            'a string',
            'another string',
            500,
            1000
        ]
    },
    'key5': {
        'key1': [
            {
                'key1': 'a string'
            }
        ]
    }
}

Output:输出:

{
   "key1":"a something",
   "key2":"another something",
   "key3":[
      "a something",
      "another something",
      [
         1,
         2,
         3
      ],
      {
         "key1":"a something",
         "key2":"another something"
      }
   ],
   "key4":{
      "key1":"a something",
      "key2":"another something",
      "key3":[
         "a something",
         "another something",
         500,
         1000
      ]
   },
   "key5":{
      "key1":[
         {
            "key1":"a something"
         }
      ]
   }
}

A general approach (assuming you don't know in advance which key of the dict is pointing to a list) would be to iterate over the dict and check the type of its values and then iterate again into each value if needed.一般方法(假设您事先不知道 dict 的哪个键指向列表)是迭代 dict 并检查其值的类型,然后在需要时再次迭代到每个值。

In your case, your dictionary may contain a list of dictionaries as values, so it is enough to check if a value is of type list, if so, iterate over the list and change the dicts you need.在您的情况下,您的字典可能包含一个字典列表作为值,因此检查一个值是否为列表类型就足够了,如果是,则遍历列表并更改您需要的字典。

It can be done recursively with a function like the following:它可以使用如下函数递归完成:

def f(d):
    for k,v in d.items():
        if k == 'current_value':
            d[k] = int(v)
        elif type(v) is list:
            for item in v:
                if type(item) is dict:
                    f(item)

>>> d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
>>> f(d)
>>> d
{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}  
d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}

for elem in d['datastreams']:      # for each elem in the list datastreams
    for k,v in elem.items():       # for key,val in the elem of the list 
        if 'current_value' in k:   # if current_value is in the key
            elem[k] = int(v)       # Cast it to int
print(d)

OUTPUT :输出

{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}

可以通过列表理解来完成:

d['datastreams'] = [{'current_value': int(ds['current_value'])} if ('current_value' in ds) else ds for ds in d['datastreams']]

You can use ast.literal_eval to evaluate the underlying value for items with current_value key in the d['datastreams'] list.您可以使用 ast.literal_eval 来评估 d['datastreams'] 列表中具有current_value键的items的基础值。 Then check whether the type is an int using isinstance for such values.然后使用isinstance来检查类型是否为int类型的值。 Finally, type cast such values to int .最后,将这些值类型转换为int

import ast
d = {'id': '10', 'datastreams': [{'current_value': '5'}, {'current_value': '4'}]}
for i in d['datastreams']:
    for k,v in i.items():
        if 'current_value' in k and isinstance(ast.literal_eval(v),int):
            i[k] = int(v)
#Output:
print(d)
{'id': '10', 'datastreams': [{'current_value': 5}, {'current_value': 4}]}

You could use this method which would loop through checks for current_value in list and change it to integer by passing the value through int() function:您可以使用此方法循环检查列表中的 current_value 并通过将值传递给 int() 函数将其更改为整数:

for value in d.values():
    for element in value:
        if 'current_value' in element:
            element['current_value'] = int(element['current_value'])

Taking alec_djinn's solution little farther to handle also nested dicts:进一步采用 alec_djinn 的解决方案来处理嵌套的字典:

def f(d):
    for k,v in d.items():
        if k == 'current_value':
            d[k] = int(v)
        elif type(v) is list:
            for item in v:
                if type(item) is dict:
                    f(item)
        if type(v) is dict:
            f(v)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM