【问题标题】:Getting nested dictionary from JSON using recursive function in python使用python中的递归函数从JSON获取嵌套字典
【发布时间】:2020-08-18 03:32:42
【问题描述】:

这是我的 JSON 数据。 JSON 数据包含一些属性,但我只需要命令和子命令属性。

{
  command: 'abc',
  depth: 1,
  help: '...',
  subcommands:[
    {
      command: 'abc folder',
      depth: 2,
      help: '...',
      subcommands:[
        {
          command: 'abc folder add',
          depth: 3,
          help: '...',
          subcommands:[
            {
              command: 'abc folder add id',
              depth: 4,
              help: '...',
              subcommands: []
            },
            {
              command: 'abc folder add type',
              depth: 4,
              help: '...',
              subcommands: []
            },
            {
              command: 'abc folder add name',
              depth: 4,
              help: '...',
              subcommands: []
            }]
        }],
        {
          command: 'abc folder list',
          depth: 3,
          help: '...',
          subcommands: []
        },
        {
          command: 'abc folder view',
          depth: 3,
          help: '...',
          subcommands: [
            {
              command: 'abc folder view id',
              depth: 4,
              help: '...',
              subcommands: []
            },
            {
              command: 'abc folder view type',
              depth: 4,
              help: '...',
              subcommands: []
            },
            {
              command: 'abc folder view name',
              depth: 4,
              help: '...',
              subcommands: []
            }
        }]
    }]
}

我想从 JSON 数据中检索的嵌套字典如下:

{
  'abc':
    {
      'folder':
        {
          'add':
            {
              'id': {},
              'type': {},
              'name': {}
            },
          'list': {},
          'view':
            {
              'id': {},
              'type': {},
              'name': {}
            }
        }
    }
}

我需要使用递归函数,以便它适用于更深层次的属性。 它只需要使用命令和子命令。 如果有子命令的值是空的,那么在结果中,相关属性的值也应该是空的。 请发布您的建议,以有效地制作嵌套 python 字典。

我们将不胜感激您的所有回答。 谢谢。

【问题讨论】:

    标签: python dictionary recursion nested


    【解决方案1】:

    一种优雅的相互递归形式 -

    def solution(t = {}):
    
      def one(t, pre):
        if not t:
          return {}
        if isinstance(t, dict):
          return \
            { t['command'][len(pre):]: 
                one
                  ( t['subcommands']
                  , t['command'] + ' '
                  )
            }
        elif isinstance(t, list):
          return many(t, pre)
        else:
          raise TypeError
    
      def many(ts, pre):
        if not ts:
          return {}
        else:
          return { **one(ts[0], pre), **many(ts[1:], pre) }
    
      return one(t, "")
    

    正如@Ajax1234 指出的那样,您必须修复您的输入subcommands 才能使用list -

    d = \
      {'command': 'abc', 'depth': 1, 'help': '...', 'subcommands': [{'command': 'abc folder', 'depth': 2, 'help': '...', 'subcommands': [{'command': 'abc folder add', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder add id', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add type', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add name', 'depth': 4, 'help': '...', 'subcommands': []}]}, {'command': 'abc folder list', 'depth': 3, 'help': '...', 'subcommands': []}, {'command': 'abc folder view', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder view id', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view type', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view name', 'depth': 4, 'help': '...', 'subcommands': {}}]}]}]}
    
    print(json.dumps(solution(d), indent = 2))
    

    输出 -

    {
      "abc": {
        "folder": {
          "add": {
            "id": {},
            "type": {},
            "name": {}
          },
          "list": {},
          "view": {
            "id": {},
            "type": {},
            "name": {}
          }
        }
      }
    }
    

    【讨论】:

    • 我的错.. 它使用列表作为子命令。我忘了加方括号。我的问题现在已编辑
    【解决方案2】:

    如果不将 subcommands 键映射到它们实际表示的命令列表,则无法将您的结构转换为有效的 Python 字典。然后, 您可以使用str.replace 进行递归:

    from functools import reduce
    data = {'command': 'abc', 'depth': 1, 'help': '...', 'subcommands': [{'command': 'abc folder', 'depth': 2, 'help': '...', 'subcommands': [{'command': 'abc folder add', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder add id', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add type', 'depth': 4, 'help': '...', 'subcommands': []}, {'command': 'abc folder add name', 'depth': 4, 'help': '...', 'subcommands': []}]}, {'command': 'abc folder list', 'depth': 3, 'help': '...', 'subcommands': []}, {'command': 'abc folder view', 'depth': 3, 'help': '...', 'subcommands': [{'command': 'abc folder view id', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view type', 'depth': 4, 'help': '...', 'subcommands': {}}, {'command': 'abc folder view name', 'depth': 4, 'help': '...', 'subcommands': {}}]}]}]}
    def get_d(d, p = None):
      return {d['command'] if p is None else d['command'].replace(p, '')[1:]:\
         reduce(lambda x, y:{**x, **y}, [get_d(i, d['command']) for i in d['subcommands']], {})}
    

    import json
    print(json.dumps(get_d(data), indent=4))
    

    输出:

    {
      "abc": {
         "folder": {
             "add": {
                "id": {},
                "type": {},
                "name": {}
             },
             "list": {},
             "view": {
                 "id": {},
                 "type": {},
                 "name": {}
              }
           }
       }
    }
    

    【讨论】:

    • 我的错.. 它使用列表作为子命令。我忘了加方括号。我的问题现在已编辑
    猜你喜欢
    • 2021-12-04
    • 2022-06-23
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    • 2016-02-05
    • 2021-08-31
    • 2013-08-01
    • 2019-06-16
    相关资源
    最近更新 更多