簡體   English   中英

制表符格式的嵌套字符串到嵌套列表〜Python

[英]Tab Formatted Nested String to Nested List ~ Python

大家好 ,在設法通過使用Beautiful Soup抓取來獲取一些數據之后……我想格式化該數據,以便可以輕松地將其導出為CSV和JSON。

我的問題是,如何翻譯此內容

Heading :
    Subheading :

AnotherHeading : 
    AnotherSubheading :
        Somedata

Heading :
    Subheading :

AnotherHeading : 
    AnotherSubheading :
        Somedata

變成這個

[
['Heading',['Subheading']],
['AnotherHeading',['AnotherSubheading',['Somedata']]],
['Heading',['Subheading']],
['AnotherHeading',['AnotherSubheading',['Somedata']]]
]

為了清楚起見縮進

熱烈的感謝,感謝您對任何救援嘗試的感謝

到目前為止,我們得到了幫助:

def parse(data):
  stack = [[]]
  levels = [0]
  current = stack[0]
  for line in data.splitlines():
    indent = len(line)-len(line.lstrip())
    if indent > levels[-1]:
      levels.append(indent)
      stack.append([])
      current.append(stack[-1])
      current = stack[-1]
    elif indent < levels[-1]:
      stack.pop()
      current = stack[-1]
      levels.pop()
    current.append(line.strip().rstrip(':'))
  return stack

該代碼的問題是它返回...

[
'Heading ', 
['Subheading '], 
'AnotherHeading ', 
['AnotherSubheading ', ['Somedata'], 'Heading ', 'Subheading '], 'AnotherHeading ', 
['AnotherSubheading ', ['Somedata']]
]

這是一個副本: https : //repl.it/yvM/1

謝謝kirbyfan64sos和SuperBiasedMan

def parse(data):

  currentTab = 0
  currentList = []
  result = [currentList]

  i = 0
  tabCount = 0

  for line in data.splitlines():

    tabCount = len(line)-len(line.lstrip())

    line = line.strip().rstrip(' :')

    if tabCount == currentTab:
        currentList.append(line)

    elif tabCount > currentTab:
        newList = [line]
        currentList.append(newList)
        currentList = newList

    elif tabCount == 0:
        currentList = [line]
        result.append(currentList)

    elif tabCount == 1:
        currentList = [line]
        result[-1].append(currentList)

    currentTab = tabCount

    tabCount = tabCount + 1
    i = i + 1

  print(result)

首先,您要清除不必要的空格,因此您要列出所有包含空格以外的行,並設置主循環的所有默認值。

teststring = [line for line in teststring.split('\n') if line.strip()]
currentTab = 0
currentList = []
result = [currentList]

此方法依賴於列表的可變性,因此將currentList設置為空列表,然后將result設置為[currentList]是重要的步驟,因為我們現在可以追加到currentList

for line in teststring:
    i, tabCount = 0, 0

    while line[i] == ' ':
        tabCount += 1
        i += 1
    tabCount /= 8

這是我想到的在每行開頭檢查制表符的最佳方法。 另外,是的,您會注意到我實際上檢查的是空格,而不是制表符。 制表符僅100%無法正常工作,我認為這是因為我沒有安裝Python 3,所以一直在使用repl.it。 它在Python 2.7上可以很好地工作,但是我不會輸入未經驗證的代碼。 如果您確認使用\\t並刪除tabCount /= 8會產生期望的結果,則可以對此進行編輯。

現在,檢查行的縮進程度。 如果它與我們的currentTab值相同,則只需追加到currentList

    if tabCount == currentTab:
        currentList.append(line.strip())

如果更高,則意味着我們已經進入了更深的列表級別。 我們需要一個嵌套在currentList的新列表。

    elif tabCount > currentTab:
        newList = [line.strip()]
        currentList.append(newList)
        currentList = newList

向后移動比較棘手,因為數據僅包含3個嵌套級別,所以我選擇對值0和1進行硬編碼(2應該總是導致上述塊之一)。 如果沒有標簽,我們可以將新列表附加到result

    elif tabCount == 0:
        currentList = [line.strip()]
        result.append(currentList)

一個選項卡的深層標題幾乎相同,除了您應該附加到result[-1] ,因為這是嵌套的最后一個主要標題。

    elif tabCount == 1:
        currentList = [line.strip()]
        result[-1].append(currentList)

最后,確保將currentTab更新為當前的tabCount ,以便下一次迭代正常進行。

    currentTab = tabCount

就像是:

def parse(data):
    stack = [[]]
    levels = [0]
    current = stack[0]
    for line in data.splitlines():
        indent = len(line)-len(line.lstrip())
        if indent > levels[-1]:
            levels.append(indent)
            stack.append([])
            current.append(stack[-1])
            current = stack[-1]
        elif indent < levels[-1]:
            stack.pop()
            current = stack[-1]
            levels.pop()
        current.append(line.strip().rstrip(':'))
    return stack[0]

不過,您的格式看起來很像YAML; 您可能需要研究PyYAML。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM