Python过滤嵌套字典给定的键名列表

use*_*560 2 python recursion

有没有办法在Python中过滤嵌套字典,这样我只能看到我指定的键?例子:

x = {
  "field": [
    {
      "nm_field": "ch_origem_sistema_chave",
      "inf_tabelado": {
        "dropdown_value": "",
        "dropdown_key": "",
        "url_lista": "",
        "chave_relacional": ""
      },
    },
    {
      "nm_field": "ax_andamento_data",
      "inf_tabelado": {
        "dropdown_value": "",
        "dropdown_key": "",
        "url_lista": "",
        "chave_relacional": ""
      },
    }
  ],
  "_metadata": {
    "dt_reg": "22/01/2014 16:17:16",
    "dt_last_up": "10/04/2014 16:30:44",
  },
  "url_detalhes": "/DetalhesDocsPro.aspx",
  "url_app": "/docspro",
}

y = filter(x, ['dropdown_value', 'nm_field', 'url_app', 'dt_reg'])
Run Code Online (Sandbox Code Playgroud)

那么 var y 会是这样的:

{
  "field": [
    {
      "nm_field": "ch_origem_sistema_chave",
      "inf_tabelado": {
        "dropdown_value": "",
      },
    },
    {
      "nm_field": "ax_andamento_data",
      "inf_tabelado": {
        "dropdown_value": "",
      },
    }
  ],
  "_metadata": {
    "dt_reg": "22/01/2014 16:17:16",
  },
  "url_app": "/docspro",
}
Run Code Online (Sandbox Code Playgroud)

我尝试使用 defaultdict 做一些事情,但在任何递归级别的列表上都没有成功。我还发现在使用不同的数据结构时遇到困难。

Rob*_*tts 6

这是 2rs2ts 答案的修改版本,它返回一个新对象而不是修改旧对象(并处理非叶节点上的过滤):

import copy

def fltr(node, vals):
    if isinstance(node, dict):
        retVal = {}
        for key in node:
            if key in vals:
                retVal[key] = copy.deepcopy(node[key])
            elif isinstance(node[key], list) or isinstance(node[key], dict):
                child = fltr(node[key], vals)
                if child:
                    retVal[key] = child
        if retVal:
             return retVal
        else:
             return None
    elif isinstance(node, list):
        retVal = []
        for entry in node:
            child = fltr(entry, vals)
            if child:
                retVal.append(child)
        if retVal:
            return retVal
        else:
            return None
Run Code Online (Sandbox Code Playgroud)

这样,您将调用

y = fltr(x, ['dropdown_value', 'nm_field', 'url_app', 'dt_reg'])
Run Code Online (Sandbox Code Playgroud)

并得到

{
    "field": [
        {
            "inf_tabelado": {
                "dropdown_value": ""
            },
            "nm_field": "ch_origem_sistema_chave"
        },
        {
            "inf_tabelado": {
                "dropdown_value": ""
            },
            "nm_field": "ax_andamento_data"
        }
    ],
    "url_app": "/docspro",
    "_metadata": {
        "dt_reg": "22/01/2014 16:17:16"
    }
}
Run Code Online (Sandbox Code Playgroud)

None请注意,如果所有内容都被过滤,这将返回。例如,

fltr(x, [])
Run Code Online (Sandbox Code Playgroud)

总会回来None,无论发生什么x