Python递归:从平面列表中嵌套列表

时间:2015-01-01 11:19:23

标签: python recursion

我需要弄清楚如何创建(我认为需要的)递归函数。我的大脑从来没有很好地应对递归。

我有一个扁平的项目集合,需要根据每个项目中的值将其转换为嵌套集合。 除了其他属性之外,每个项目都具有类型。一个可能的item.type是" group header"。每个"组标题"将由"组页脚"关闭。我需要根据这两种类型嵌套集合。

该集合可能如下所示:

  • 第1项:type = blurb
  • 第2项:type = group header
  • 第3项:type = question
  • 第4项:type = question
  • 第5项:type = group header
  • 第6项:type = question
  • 第7项:type = question
  • 第8项:type = group footer
  • 第9项:type = question
  • 第10项:type = group footer

我想让这个集合看起来更像这样:

  • 第1项:blurb
  • 第2项:标题,第10项:页脚
    • 第3项:问题
    • 第4项:问题
    • 第5项:组头,第8项:页脚
      • 第6项:问题
      • 第7项:问题
    • 第9项:问题

可以有任何深度的嵌套,因此(我认为)需要递归。

关于如何做到这一点的任何指示非常感谢。我根本无法理解它,我无法在网上找到一个示例,其中标签(在我的情况下,"组页脚")用于跳回巢级别。

以下是python小提琴的开头: http://pythonfiddle.com/recursion-fiddle-ninety-nine

来自链接的示例数据:

test_data = [{"id":1, "type":"blurb", "info":"This is the blurb"},
            {"id":2, "type":"header", "info":"This is the first group header"},
            {"id":3, "type":"question", "info":"This is the first question"},
            {"id":4, "type":"question", "info":"This is the second question"},
            {"id":5, "type":"header", "info":"This is the second group header"},
            {"id":6, "type":"question", "info":"This is the third question"},
            {"id":7, "type":"question", "info":"This is the fourth question"},
            {"id":8, "type":"footer", "info":"This is the footer for the second header"},
            {"id":9, "type":"question", "info":"This is the fifth question"},
            {"id":10, "type":"footer", "info":"This is the footer for the first header"}]

提前致谢

1 个答案:

答案 0 :(得分:3)

我不知道您希望如何格式化结果列表,但是在这里:

nested_data = []
stack= []
for item in test_data:
    if item['type']=='header': # if it's a header
        # add [item] to the list (the footer will be appended to this later)
        header= [[item]]
        nested_data.append(header)
        # push this list onto the stack so we can continue appending to it
        # after we've found the footer
        stack.append(nested_data)
        nested_data= header
    elif item['type']=='footer':
        # if it's a footer, pop the last list off the stack
        nested_data= stack.pop(-1)
        # and append the footer after the header so that
        # [header, footer] is the first item
        nested_data[-1][0].append(item)
    else:
        # if it's just a boring ol' item, all we need do is append it
        nested_data.append(item)

这会产生(nested_data变量保存结果):

[
  {
    "info": "This is the blurb", 
    "type": "blurb", 
    "id": 1
  }, 
  [
    [
      {
        "info": "This is the first group header", 
        "type": "header", 
        "id": 2
      }, 
      {
        "info": "This is the footer for the first header", 
        "type": "footer", 
        "id": 10
      }
    ], 
    {
      "info": "This is the first question", 
      "type": "question", 
      "id": 3
    }, 
    {
      "info": "This is the second question", 
      "type": "question", 
      "id": 4
    }, 
    [
      [
        {
          "info": "This is the second group header", 
          "type": "header", 
          "id": 5
        }, 
        {
          "info": "This is the footer for the second header", 
          "type": "footer", 
          "id": 8
        }
      ], 
      {
        "info": "This is the third question", 
        "type": "question", 
        "id": 6
      }, 
      {
        "info": "This is the fourth question", 
        "type": "question", 
        "id": 7
      }
    ], 
    {
      "info": "This is the fifth question", 
      "type": "question", 
      "id": 9
    }
  ]
]