递归地重命名字典列表中的字典键

Posted

技术标签:

【中文标题】递归地重命名字典列表中的字典键【英文标题】:Rename dict keys in a list of dicts recursively 【发布时间】:2022-01-17 19:27:18 【问题描述】:

我想了解如何在不改变方法参数的情况下递归地重命名字典列表中的键。

我有以下字典列表:

filters = [
    
        'or': [
        
                'and': [
                
                    "column": 
                        "type": "string",
                        "name": "field_name"
                    ,
                    "operator": "==",
                    "value": "field_value"
                ,
                
                    "column": 
                        "type": "string",
                        "name": "field_2_name"
                    ,
                    "operator": "!=",
                    "value": "field_2_value"
                
            ]
        ,
        
                'not': [
                
                    "column": 
                        "type": "number",
                        "name": "field_3_name"
                    ,
                    "operator": "==",
                    "value": "field_3_value"
                
            ]
        
    ]
]

这是我期望达到的目标:

filters = [
    
        'or': [
            
                'and': [
                    'field': 'field_name', 'op': '==', 'value': 'field_value',
                    'field': 'field_2_name', 'op': '!=', 'value': 'field_2_value',
                ]
            ,
            
                'not': [
                    'field': 'field_3_name', 'op': '==', 'value': 'field_3_value'
                ]
            ,
        ],
    

]

有什么办法可以解决这个问题?

谢谢!

【问题讨论】:

您不能重命名密钥。您可以使用旧值插入新键并删除旧键:值对。你尝试了什么? minimal reproducible example? without mutation of method parameters 是什么意思? 感谢您的提醒。我的尝试令人困惑,我没有得到任何有用的解决方案来做一个有用的例子。 @tobias_k 成功了!还是谢谢你。 【参考方案1】:

一个递归函数应该可以工作,如果它们包含column,则更改子字典,否则为其他操作进行更深层次的递归。

def change(collection):
    if isinstance(collection, list):
        return [change(d) for d in collection]
    if isinstance(collection, dict):
        if "column" in collection:
            return 
                "field": collection["column"]["name"],
                "value": collection["value"],
                "op": collection["operator"]
            
        else:
            return op: change(val) for op, val in collection.items()

res = change(filters)

结果:

['or': ['and': ['field': 'field_name', 'op': '==', 'value': 'field_value',
                  'field': 'field_2_name', 'op': '!=', 'value': 'field_2_value'],
         'not': ['field': 'field_3_name', 'op': '==', 'value': 'field_3_value']]]

【讨论】:

感谢您的建议。这就像一个魅力而不改变过滤器。【参考方案2】:

很简单,您编写一个递归函数来修复您的数据结构。我假设您不想更改原件。

def fixup(d):
    if isinstance(d,list):
        return [fixup(x) for x in d]
    elif not isinstance(d,dict):
        return d
    elif needs_mangling(d):
        return mangler(d)
    else:
        return k:fixup(v) for k,v in d.items()

根据需要添加修饰函数。

【讨论】:

【参考方案3】:

这是否满足您的方案?

def change(obj):
    # if recusive parameter is a list
    if isinstance(obj, list):
        # run next recursive iteration for each item in list
        for i in range(len(obj)):
            obj[i] = change(obj[i])
        return obj

    # if parameter is a dict
    if isinstance(obj, dict):
        # 1st case is to convert the object
        if "operator" in obj:
            return "field": obj["column"]["name"], "op": obj["operator"], "value": obj["value"]

        # 2nd case is to go deeper into recursion with object values
        else:
            for key in obj:
                obj[key] = change(obj[key])
            return obj


print(change(filters))

【讨论】:

以上是关于递归地重命名字典列表中的字典键的主要内容,如果未能解决你的问题,请参考以下文章

php递归键重命名仅用于内部数组

根据存储在 data.frame 中的单独字符向量,有条件地重命名列表中的列

使用 find 和 sed 递归地重命名文件

如何在 MacOS 中递归地重命名文件夹和文件

如何重命名字典列表中深度嵌套的键(Python 3)?

将嵌套命名元组的列表展平为字典列表