Algorithmus - Nummerierung für TOC (Inhaltsverzeichnis)

stimmen
3

Ich möchte eine VBA-Funktion Anzahl Excel-Zeilen auf die Gruppierung Tiefe der Reihe basiert umzusetzen.

Aber ich denke, ein allgemeiner Algorithmus für TOCs ist interessanter zu erzeugen.

Das Problem ist:

Bei einer Liste der „gegliederter“ Zeilen wie

One
 Two
  Three
   Four
 Five
Six

(Die „Einrückungsniveau“ kann davon ausgegangen werden, bekannt sein, und ein Teil der Eingangsdaten)

So generieren Sie die folgende Ausgabe:

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

Natürlich ist mein Code und läuft ... und auch unter THWoS versteckt (The Heavy Weight of Shame)

Veröffentlicht am 01/06/2010 um 00:20
quelle vom benutzer
In anderen Sprachen...                            


2 antworten

stimmen
8

Verwenden Sie einen Stapel für die Zahlen. Schleife durch jede Zeile, und prüfen Sie den Einrückungsniveau jeder Reihe, ohne Einbuchtung wobei Ebene 1.

  1. Wenn die aktuelle Einrückungsebene größer ist als die Größe des Stapels Push so viele Einsen ist als der Unterschied auf den Stapel ist (die Differenz in der Regel nur einer wäre, aber das funktioniert auch, wenn jemand eine Überschrift der Ebene 3 unter einer Überschrift der Ebene 1 setzt, zum Beispiel)
  2. Wenn die aktuelle Einrückungsebene kleiner ist als die Größe des Stapels, Pop und verwerfen so viele Zahlen wie der Unterschied ist, und dann auf dem Stapel die obere Zahl zu erhöhen.
  3. Wenn die aktuelle Einrückungsniveau der Größe des Stapels entspricht, inkrementiert die obere Zahl auf dem Stapel

Für jede Zeile ist die aktuelle Titelnummer die Zahlen auf dem Stapel mit einem verketteten zusammen. trennen sie.

Beachten Sie, wie die Größe des Stapels handlicher der vorhergehenden Zeile des Einrückungsebene darstellt.

Für Menschen, die es leichter lesen Code zu finden, hier ist eine JavaScript-Implementierung für modernen Browser:

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

Beantwortet am 01/06/2010 um 00:33
quelle vom benutzer

stimmen
2

Dieser Algorithmus geht davon aus, dass Einrückungsebene nie um mehr als 1 Einheit erhöht. Ist dies der Fall, dann müssen Sie alle „übersprungen“ Ebenen auf 1 gesetzt.

#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
Beantwortet am 01/06/2010 um 00:42
quelle vom benutzer

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