【问题标题】: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 成功了!还是谢谢你。

标签: python list dictionary recursion mutation


【解决方案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))
    

    【讨论】:

      猜你喜欢
      • 2020-12-24
      • 2013-05-04
      • 1970-01-01
      • 2016-09-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-30
      相关资源
      最近更新 更多