代码之家  ›  专栏  ›  技术社区  ›  AutoTester213

Python-动态构建嵌套树

  •  0
  • AutoTester213  · 技术社区  · 7 年前

    我正在尝试用python构建一个树层次结构,假设我有他的结构,我需要能够动态地添加更多的子元素,例如 Bannana .

    更新: Apple(Children) 对Lemon和其他孩子也一样。苹果节点也是根节点。

    Apple
       Bannana
       Lemon
          Juice
            Drink
       Watermelon
           Red
             Round
    

    Apple
       Bannana
       Lemon
          Juice
            Drink
              Watermelon
           Red
              Round
    

    如果是这样的话

    {
        'Apple': 'Fruit',
        'children': [{
            'Bannana': 'fruit',
            'children': None
        },  {
            'Lemon': 'Fruit',
            'children': [{
                'Juice': 'Food',
                'children': [{
                    'Drink': 'Action',
                    'children': None
                 And so on...
    

    如何使层次结构动态化?例如,特定父项下的行数?

    我从我找到的一个例子中尝试过类似的东西

    import collections
    def add_element(root, path, data):
        if len(path) == 1:
            root[path[0]] = data
        else:
            add_element(root[path[0]], path[1:], data)
    
    count = 1
    
    
    tree = lambda: collections.defaultdict(tree)
    root = tree()
    n= 10
    for i in range(1,n):
        path_list= ['Apple', 'Lemon', 'Juice' + str(count)]
        print (path_list)
        count += 1
        add_element(root,path_list, 1 )
    print (root)
    

    编辑1

    args = {'Apple': 'Apple', 'Lemon': 'Lemon', 'Juice': 'Juice', 'Drink': 'Drink'}
    
    s = """
    {Apple}
       {Lemon}
          {Juice}
             {Drink}
    """.format(**args)
    
    def group_data(vals):
      if len(vals) == 1:
         return {vals[0]:'Fruit', 'Children':None}
      new_data = [list(b) for _, b in itertools.groupby(vals, key=lambda x:bool(re.findall('^\s', x)))]
      new_group = [[new_data[i], new_data[i+1]] for i in range(0, len(new_data), 2)]
      result = []
      for a, b in new_group:
         result.extend([{i:'Fruit', 'Children':None} for i in a[:-1]])
         result.append({a[-1]:'Fruit', 'Children':group_data([re.sub('^\s{3}', '', c) for c in b])})
      return result
    
    _new_data = [i.strip('\n') for i in filter(None, s.split('\n'))]
    
    
    print(json.dumps(group_data(_new_data), indent=4))
    

    这工作很好,但它仍然硬编码,这不是我要找的。

    1 回复  |  直到 7 年前
        1
  •  1
  •   Ajax1234    7 年前

    您可以分析每个水果前的空格:

    s = """
    Apple
       Bannana
       Lemon
          Juice
             Drink
                Watermelon
          Red
             Round
    """
    

    import itertools, re
    def group_data(vals):
      if len(vals) == 1:
         return {vals[0]:'Fruit', 'Children':None}
      new_data = [list(b) for _, b in itertools.groupby(vals, key=lambda x:bool(re.findall('^\s', x)))]
      new_group = [[new_data[i], new_data[i+1]] for i in range(0, len(new_data), 2)]
      result = []
      for a, b in new_group:
         result.extend([{i:'Fruit', 'Children':None} for i in a[:-1]])
         result.append({a[-1]:'Fruit', 'Children':group_data([re.sub('^\s{3}', '', c) for c in b])})
      return result
    
    _new_data = [i.strip('\n') for i in filter(None, s.split('\n'))]
    

    import json
    print(json.dumps(group_data(_new_data), indent=4))
    

    输出:

    [
         {
           "Apple": "Fruit",
           "Children": [
             {
                "Bannana": "Fruit",
                "Children": null
               },
               {
                   "Lemon": "Fruit",
                   "Children": [
                      {
                          "Juice": "Fruit",
                           "Children": [
                                {
                                 "Drink": "Fruit",
                                 "Children": {
                                     "Watermelon": "Fruit",
                                     "Children": null
                                  }
                              }
                          ]
                      },
                      {
                           "Red": "Fruit",
                           "Children": {
                              "Round": "Fruit",
                              "Children": null
                         }
                      }
                  ]
              }
           ]
        }
    ]