Python - 迭代和更新嵌套的字典和列表

10

有以下字典,其中某些值可以是字典的列表:

{
  "A": [
    {
      "B": {
        "C": "D",
        "X": "CHNAGE ME"
      }
    },
    {
      "E": "F"
    }
  ],
  "G": {
    "Y": "CHANGE ME"
  }
}

我想要递归遍历这些项,并改变值为"CHANGE ME"的键值对,使结果如下:

{
  "A": [
    {
      "B": {
        "C": "D",
        "X.CHANGED": "CHANGED"
      }
    },
    {
      "E": "F"
    }
  ],
  "G": {
    "Y.CHANGED": "CHANGED"
  }
}

我找到的解决方案没有处理值为列表的情况,例如:

import collections
def nested_dict_iter(nested):
    for key, value in nested.iteritems():
        if isinstance(value, collections.Mapping):
            for inner_key, inner_value in nested_dict_iter(value):
                yield inner_key, inner_value
        else:
            yield key, value

我该如何实现我的目标?


3
更新涉及替换键通常比它的价值更麻烦,只需创建一个新的数据结构即可。 - juanpa.arrivillaga
您可以使用在此处用于展平的逻辑:https://stackoverflow.com/questions/55294445/how-can-i-flatten-dict-containing-list-by-considering-its-index-as-key - Harsha Biyani
2个回答

11

使用递归

例子:

def update(data):
    for k, v in data.copy().items():
        if isinstance(v, dict):     # For DICT
            data[k] = update(v)
        elif isinstance(v, list):   # For LIST
            data[k] = [update(i) for i in v]
        elif v == 'CHANGE ME':      # Update Key-Value
            # data.pop(k)
            # OR
            del data[k]
            data[f"{k}.CHANGED"] = 'CHANGED'
    
    return data

print(update(data))

输出:

{
    'A':[{'B': {'C': 'D', 'X.CHANGED': 'CHANGED'}}, {'E': 'F'}], 
    'G':{'Y.CHANGED': 'CHANGED'}
 }

注意:我没有测试所有边角情况


这对我很有帮助。谢谢。我建议进行一个更新:要注意列表,因为它们没有data.copy.items()方法。对于列表,您需要使用enumerate(data.copy()) - JaXt0r
@Rakesh,你能为这个问题提供任何解决方案吗?https://stackoverflow.com/q/73069851/1138192 - A l w a y s S u n n y

0
对于我的情况,我需要替换一些关键字符以便存储在数据库中。我还发现需要处理数组包含非字典元素的情况(在这些类型上执行复制操作会失败)。基于Rakesh的解决方案进行改进:
def filter_dict_keys(data):
    if isinstance(data, str) or isinstance(data, int):
        return data
    for k, v in data.copy().items():
        if isinstance(v, dict):
            v = filter_dict_keys(v)
        if isinstance(v, list):
            v = [filter_dict_keys(i) for i in v]
        if '.' in k:
            del data[k]
            data[k.replace('.', ';')] = v
    return data

例子:

>>> a = {'1': '1', '2': ['2', '3', '4', '5.5', {'6.6': '6.6'}], '7': {'8': '8', '9': '9', '10': {'1.1': {'1.2': '1.3'}}}}
>>> filter_dict_keys(a)
{'1': '1', '2': ['2', '3', '4', '5.5', {'6;6': '6.6'}], '7': {'8': '8', '9': '9', '10': {'1;1': {'1;2': '1.3'}}}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接