2010-06-28 75 views
3

嵌套列表生成內容的表,我有一個Python列表中的可用這些數據:生成扁平化數據在Python

data = [ 
    {title: 'Section 1', level: 1, page_number: 1}, 
    {title: 'Section 1.1', level: 2, page_number: 2}, 
    {title: 'Section 1.2', level: 2, page_number: 3}, 
    {title: 'Section 2', level: 1, page_number: 4}, 
    {title: 'Section 2.1', level: 2, page_number: 5}, 
    {title: 'Section 3', level: 1, page_number: 6}, 
] 

由此,我想獲得這種嵌套結構的,與使用模板引擎更兼容:

toc = [ 
    {title: 'Section 1', page_number: 1, sub: [ 
     {title: 'Section 1.1', page_number: 2, sub: []}, 
     {title: 'Section 1.2', page_number: 3, sub: []}, 
    ]}, 
    {title: 'Section 2', page_number: 4, sub: [ 
     {title: 'Section 2.1', page_number: 5, sub: []},  
    ]}, 
    {title: 'Section 3', page_number: 6, sub: []}, 
] 

有關如何實現此目的的提示?我嘗試了遞歸函數,但對於我有限的大腦來說,它變得非常棘手。

任何幫助非常感謝。

編輯:增加了一個事實,一個條目最終可以沒有孩子。對不起,錯過了。

+0

不需要遞歸,循環和像列表結構一樣的堆棧也可以工作。 – Ofir 2010-06-28 08:38:17

回答

4

假設章節進來順序,這意味着孩子章總是父母后,並沒有缺失的父(跳過級):

import pprint 

data = [ 
    {'title': 'Section 1', 'level': 1, 'page_number': 1}, 
    {'title': 'Section 1.1', 'level': 2, 'page_number': 2}, 
    {'title': 'Section 1.2', 'level': 2, 'page_number': 3}, 
    {'title': 'Section 2', 'level': 1, 'page_number': 4}, 
    {'title': 'Section 2.1', 'level': 2, 'page_number': 42}, 
    {'title': 'Section 2.1.1', 'level': 3, 'page_number': 42}, 
    {'title': 'Section 3', 'level': 1, 'page_number': 42}, 
] 

toc = [] 
stack = [toc] 
for d in data: 
    d['sub'] = [] 
    while d['level'] < len(stack): 
     stack.pop() 
    while d['level'] > len(stack): 
     stack.append(stack[-1][-1]['sub']) 
    stack[-1].append(d) 


pprint.pprint(toc) 

結果:

[{'level': 1, 
    'page_number': 1, 
    'sub': [{'level': 2, 'page_number': 2, 'sub': [], 'title': 'Section 1.1'}, 
      {'level': 2, 'page_number': 3, 'sub': [], 'title': 'Section 1.2'}], 
    'title': 'Section 1'}, 
{'level': 1, 
    'page_number': 4, 
    'sub': [{'level': 2, 
      'page_number': 42, 
      'sub': [{'level': 3, 
        'page_number': 42, 
        'sub': [], 
        'title': 'Section 2.1.1'}], 
      'title': 'Section 2.1'}], 
    'title': 'Section 2'}, 
{'level': 1, 'page_number': 42, 'sub': [], 'title': 'Section 3'}] 

編輯:改變它有沒有孩子的空'子'項目。在編輯歷史記錄中查看其他變體。

+0

啊,我應該在聲明中指出,部分可以沒有孩子......但這裏有很棒的東西,值得深思的食物 – NiKo 2010-06-28 08:55:37

+0

嘿,你很快。好吧,它現在如預期的那樣工作,非常感謝:) – NiKo 2010-06-28 08:58:39

+0

@NiKo區別不在於一個部分不能有子女(這很明顯),而是如果你想在這種情況下有一個空'子'條目。我的第一個代碼沒有把空的'子',這個。 – unbeli 2010-06-28 09:00:37

0

您可以遍歷列表中的每個條目並從那裏創建一個新列表。無論何時出現「Section x.y」,您都會在sub下添加它。

newData = [] 
curParent = None 
for d in data: 
    # child 
    if d['title'].find('.') > 0: 
    assert curParent # Make sure we have a valid parent dictionary 
    curParent['sub'].append({'title': d['title'], 'page_number': d['page_number']) 
    # parent 
    else: 
    curParent = {'title': d['title'], 'page_number': d['page_number'], 'sub': []} 
    newData.append(curParent) 

這應該工作2或3級,如果你需要更多比不同的方法可能會更好。此外,find('。')可能不適用於其他標題,但要麼使用級別字段(在您的示例中似乎是冗餘的)或正則表達式。

+0

是的,我可以有很多嵌套關卡。另外,我並不是真的想依靠節標題中的點號;) – NiKo 2010-06-28 09:34:45

+0

對每個不合適的答案進行降調並不是很好。這不像我故意寫錯了什麼,它只是另一種方法而不是其他方法。 – tobiw 2010-06-28 10:15:57

2

這是做你想做的嗎?

TITLE, LEVEL, PAGE_NUMBER, SUB = 'title', 'level', 'page_number', 'sub' 
data = [ 
    {TITLE: 'Section 1', LEVEL: 1, PAGE_NUMBER: 1}, 
    {TITLE: 'Section 1.1', LEVEL: 2, PAGE_NUMBER: 2}, 
    {TITLE: 'Section 1.1.1', LEVEL: 3, PAGE_NUMBER: 2}, 
    {TITLE: 'Section 1.2', LEVEL: 2, PAGE_NUMBER: 3}, 
    {TITLE: 'Section 2', LEVEL: 1, PAGE_NUMBER: 4}, 
    {TITLE: 'Section 2.1', LEVEL: 2, PAGE_NUMBER: 5}, 
] 

levels = [ { SUB: [] } ] 
for section in data: 
    section = dict(section) 
    current = section[LEVEL] 
    section[SUB] = [] 
    levels[current-1][SUB].append(section) 
    del levels[current:] 
    levels.append(section) 

toc = levels[0][SUB] 
from pprint import pprint 
pprint(toc) 
+0

非常好,可能比我的堆棧還要好。 – unbeli 2010-06-28 08:52:24

+0

它仍然是一個堆棧,只是略有不同。我認爲主要區別在於,您只保存了保存整個部分的每個級別的子列表。這件事是否是一個有趣的問題。 – Duncan 2010-06-28 09:03:26