【问题标题】:How to transform a flattened data to a structured json?如何将扁平化的数据转换为结构化的 json?
【发布时间】:2020-12-10 09:21:47
【问题描述】:

这是主要的扁平化元素,也就是输入数据:

['a-ab-aba-abaa-abaaa', 'a-ab-aba-abab', 'a-ac-aca-acaa', 'a-ac-aca-acab']

这是我需要的目标数据,也就是输出数据:

[
  {
    "title": "a",
    "children": [
      {
        "title": "ab",
        "children": [
          {
            "title": "aba",
            "children": [
              {
                "title": "abaa",
                "children": [
                  {
                    "title": "abaaa"
                  }
                ]
              },
              {
                "title": "abab"
              }
            ]
          }
        ]
      },
      {
        "title": "ac",
        "children": [
          {
            "title": "aca",
            "children": [
              {
                "title": "acaa"
              },
              {
                "title": "acab"
              }
            ]
          }
        ]
      }
    ]
  }
]

我以为我可以使用deep-for-loop迭代来生成这个json数据,但是太难了,因为level的num会大于10。所以我认为for-loop在这个过程中不能做,有没有任何算法或使用打包代码来实现实现此目标的功能? 如果你能分享你的想法,我非常感激,上帝保佑你!

【问题讨论】:

    标签: python json graph tree


    【解决方案1】:

    这是一个使用 itertools 的递归解决方案。我不知道这是否足以满足您的目的,但它确实有效。它的工作原理是将您的字符串列表转换为列表列表,然后将其划分为具有相同第一个键的列表,然后构建字典并在删除第一个键的情况下重复。

    from itertools import groupby
    from pprint import pprint
    
    data = ['a-ab-aba-abaa-abaaa', 'a-ab-aba-abab', 'a-ac-aca-acaa', 'a-ac-aca-acab']
    components = [x.split("-") for x in data]
    
    def build_dict(component_list):
        key = lambda x: x[0]
        component_list = sorted(component_list, key=key)
        # divide into lists with the same fist key
        sublists = groupby(component_list, key)
        result = []
    
        for name, values in sublists:
            value = {}
            value["title"] = name
            value["children"] = build_dict([x[1:] for x in values if x[1:]])
            result.append(value)
        return result
    
    pprint(build_dict(components))
    

    输出:

    [{'children': [{'children': [{'children': [{'children': [{'children': [],
                                                              'title': 'abaaa'}],
                                                'title': 'abaa'},
                                               {'children': [], 'title': 'abab'}],
                                  'title': 'aba'}],
                    'title': 'ab'},
                   {'children': [{'children': [{'children': [], 'title': 'acaa'},
                                               {'children': [], 'title': 'acab'}],
                                  'title': 'aca'}],
                    'title': 'ac'}],
      'title': 'a'}]
    

    要将此 dict 转换为 json,您可以使用 json 模块中的json.dumps。我希望我的解释清楚。

    【讨论】:

    • 这是一个很好的解决方案,我想也许你可以先检查len(component_list) > 0,然后for循环的主体将是单行的。但无论如何 +1))
    • 难以置信,这种方式效率很高,万分感谢!
    【解决方案2】:

    这是一个开始:

    def populate_levels(dct, levels):
        if levels:
            if levels[0] not in dct:
                dct[levels[0]] = {}
            populate_levels(dct[levels[0]], levels[1:])
    
    
    def create_final(dct):
        final = []
        for title in dct:
            final.append({"title": title, "children": create_final(dct[title])})
        return final
    
    
    data = ['a-ab-aba-abaa-abaaa', 'a-ab-aba-abab', 'a-ac-aca-acaa', 'a-ac-aca-acab']
    template = {}
    
    for item in data:
        populate_levels(template, item.split('-'))
    
    final = create_final(template)
    

    我看不到一个干净的方式来一次完成这一切,所以我在template 字典之间创建了这个。现在,如果“节点”没有子节点,则其对应的 dict 将包含 'children': [] 如果您愿意,可以在 create_final 函数中更改此行为。

    【讨论】:

      【解决方案3】:

      你可以使用collections.defaultdict:

      from collections import defaultdict
      def get_struct(d):
        _d = defaultdict(list)
        for a, *b in d:
           _d[a].append(b)
        return [{'title':a, 'children':get_struct(filter(None, b))} for a, b in _d.items()]
      
      data = ['a-ab-aba-abaa-abaaa', 'a-ab-aba-abab', 'a-ac-aca-acaa', 'a-ac-aca-acab']
      

      import json
      print(json.dumps(get_struct([i.split('-') for i in data]), indent=4))
      

      输出:

      [
        {
          "title": "a",
          "children": [
              {
                  "title": "ab",
                  "children": [
                      {
                          "title": "aba",
                          "children": [
                              {
                                  "title": "abaa",
                                  "children": [
                                      {
                                          "title": "abaaa",
                                          "children": []
                                      }
                                  ]
                              },
                              {
                                  "title": "abab",
                                  "children": []
                              }
                          ]
                      }
                  ]
              },
              {
                  "title": "ac",
                  "children": [
                      {
                          "title": "aca",
                          "children": [
                              {
                                  "title": "acaa",
                                  "children": []
                              },
                              {
                                  "title": "acab",
                                  "children": []
                              }
                          ]
                      }
                   ]
                }
            ]
         }
      ]
      

      【讨论】:

        猜你喜欢
        • 2011-11-15
        • 2021-11-19
        • 1970-01-01
        • 2013-11-24
        • 2017-12-16
        • 2023-03-15
        • 2017-01-07
        • 2013-12-19
        • 2019-06-22
        相关资源
        最近更新 更多