2010-05-31 48 views
3

我想實現一個VBA函數來根據行的分組深度對Excel行編號。算法 - TOC的編號(目錄)

但我認爲生成TOC的一般算法更有趣。

的問題是:

鑑於「縮進」系如

One 
Two 
    Three 
    Four 
Five 
Six 

的列表(可以假設「縮進級別」是已知的和所述輸入數據的一部分)

生成以下的輸出:

1. One 
1.1 Two 
1.1.1 Three 
1.1.1.1 Four 
1.2 Five 
2. Six 

當然我的代碼是向上和r Unning ...並且也隱藏在THWoS(恥辱的重量)下

+0

所以你有工作代碼。那麼你需要什麼? – 2010-05-31 23:23:37

+1

@Moron:我不是爲了完成我的工作,而是爲了從別人那裏學習更好的方法,也許可以幫助他們。順便說一句,你爲什麼浪費你的時間與評論? – 2010-05-31 23:49:34

+0

你從來沒有具體的問題,請閱讀常見問題:這不是一個討論板。如果我不再回復,請原諒我。 – 2010-05-31 23:56:37

回答

8

使用數字堆棧。通過每行循環,並且檢查每行的縮進層次,與無壓痕存在水平1.

  1. 如果當前縮進電平比壓棧儘可能多的人的尺寸時作爲差是到堆棧(差別通常只有一個,但是即使有人在第1級標題下放置第3級標題,也是如此)
  2. 如果當前縮進級別小於堆棧的大小,則彈出並丟棄儘可能多的數字,然後增加堆棧頂部的數字。
  3. 如果當前縮進級別等於堆的大小,遞增堆棧

對於每一行的頂部數,當前標題號碼是與串聯在一起的堆棧上的數字。將它們分開。

請注意堆棧的大小如何輕鬆地代表上一行的縮進級別。

對於誰能夠更容易地閱讀代碼的人,這裏是一個JavaScript實現現代瀏覽器:

const toc = ` 
 
One 
 
Two 
 
    Three 
 
    Four 
 
Five 
 
    Six 
 
    Seven 
 
Eight 
 
Nine 
 
Ten 
 
`; 
 

 
let stack = []; 
 

 
toc.trim().split(/\n/g).forEach(line => { 
 
    // Gets the identitation level with 1 being no indentation and so forth 
 
    let level = line.match(/^\s*/)[0].length + 1; 
 

 
    if (level > stack.length) { 
 
    while (level > stack.length) 
 
     stack.push(1); 
 
    } else { 
 
    while (level < stack.length) 
 
     stack.pop(); 
 

 
    stack[stack.length - 1]++; 
 
    } 
 
    
 
    let title = stack.join(".") + ". " + line.trim(); 
 

 
    document.body.appendChild(document.createElement("div")).innerText = title; 
 
});

2

此算法假定縮進級別從未超過1個單位增加。如果是這樣,那麼你必須將所有「跳過」級別設置爲1.

#use a vector instead, if your language supports it 
numbering = {0, 0, 0, 0, 0, 0, 0} 

for line in lines: 
    level = indentLevel(line) #starting from 0 

    numbering[level] = numbering[level] + 1 
    numbering[level + 1] = 0 #create it if it doesn't exist 
    for n = 0 to level - 1 
     print numbering[n], ".", 
    print numbering[level], " ", line