Algorytm - numeracja TOC (Table of Zawartość)

głosy
3

Chcę zaimplementować funkcję VBA na numer wierszy Excel w oparciu o głębokości Grupowanie rzędu.

Ale myślę, że ogólny algorytm generowania TOCs jest bardziej interesująca.

Problemem jest:

Biorąc pod uwagę listę „wcięte” linie takie jak

One
 Two
  Three
   Four
 Five
Six

( „Poziom wcięcie” może być uznane za znane i część danych wejściowych)

Aby wygenerować następujący wynik:

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

Oczywiście mój kod jest uruchomiony i działa ... a także ukryte pod THWoS (Heavy Weight of Shame)

Utwórz 01/06/2010 o 00:20
źródło użytkownik
W innych językach...                            


2 odpowiedzi

głosy
8

Użyj stos dla liczb. Pętli każdego rzędu i sprawdzić poziom wcięcie każdego rzędu, bez wcięć będącego poziom 1.

  1. Jeśli obecny poziom wcięcia jest większa niż rozmiar push stosu jak wielu z nich, jak różnica jest na stosie (różnica zazwyczaj będzie tylko jeden, ale to działa, nawet jeśli ktoś stawia nagłówek poziomu 3 pod poziom 1 pozycji, na przykład)
  2. Jeśli obecny poziom wcięcia jest mniejszy niż rozmiar stosu, pop i wyrzucić jak najwięcej liczb jako różnica jest, a następnie podwyższyć górną liczbę na stos.
  3. Jeśli obecny poziom wcięcia jest równa wielkości stosu, przyrost górną liczbę na stos

Dla każdego wiersza, bieżący numer tytuł numery na stosie sklejone z. aby je rozdzielić.

Zauważ, że wielkość stosu grzejniku reprezentuje poziom wcięcia poprzedniej linii za.

Dla ludzi, którzy łatwiej odczytać kod, oto realizacja JavaScript dla nowoczesnych przeglądarek:

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;
});

Odpowiedział 01/06/2010 o 00:33
źródło użytkownik

głosy
2

Algorytm ten zakłada, że ​​poziom wcięcia nie wzrasta o więcej niż 1 jednostkę. Jeśli tak, to musisz ustawić wszystkie „przeskakujemy” poziom 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
Odpowiedział 01/06/2010 o 00:42
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more