Algoritmo - numerazione per TOC (Table of Contents)

voti
3

Voglio implementare una funzione VBA per numero righe Excel in base della profondità raggruppamento della riga.

Ma penso che un algoritmo generale per la generazione di TOC è più interessante.

Il problema è:

Dato un elenco di linee rientrate come

One
 Two
  Three
   Four
 Five
Six

(Il livello di rientro può essere assume essere noto e parte dei dati di ingresso)

Per generare il seguente risultato:

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

Naturalmente il mio codice è installato e funzionante ... e anche nascosto sotto THWoS (Il peso della vergogna)

È pubblicato 01/06/2010 alle 00:20
fonte dall'utente
In altre lingue...                            


2 risposte

voti
8

Utilizzare uno stack per i numeri. Ciclo attraverso ogni fila, e controllare il livello di rientro di ogni riga, senza solco essendo livello 1.

  1. Se il livello di rientro corrente è maggiore della dimensione della spinta stack come molti quelli come la differenza è nello stack (la differenza di solito è uno solo, ma questo funziona anche se qualcuno mette un titolo di livello 3 in una rubrica di livello 1, per esempio)
  2. Se il livello di rientro corrente è minore della dimensione dello stack, pop e scartare i numeri che la differenza è quindi incrementare il numero in cima alla pila.
  3. Se il livello di rientro corrente è uguale alla dimensione dello stack, incrementare il numero in cima alla pila

Per ogni riga, il numero del titolo attuale è il numero sulla pila concatenato insieme con un. per separarli.

Si noti come la dimensione dello stack rappresenta comodamente livello di indentazione della riga precedente.

Per le persone che trovano più facile da leggere il codice, ecco un'implementazione JavaScript per i browser moderni:

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

Risposto il 01/06/2010 a 00:33
fonte dall'utente

voti
2

Questo algoritmo presuppone che livello di rientro non aumenta di più di 1 unità. Se è così, allora è necessario impostare tutti i livelli "saltato" a 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
Risposto il 01/06/2010 a 00:42
fonte dall'utente

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