Algoritme - Nummering voor TOC (Table of Contents)

stemmen
3

Ik wil VBA functie Excel aantal rijen op basis van de combinatie diepte van de rij voeren.

Maar ik denk dat een algemeen algoritme voor het genereren van TOC is interessanter.

Het probleem is:

Gegeven een lijst van ingesprongen lijnen zoals

One
 Two
  Three
   Four
 Five
Six

(De inspringniveau worden bekend verondersteld en een deel van de invoergegevens)

Om de volgende output genereren:

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

Natuurlijk is mijn code is up and running ... en ook verborgen onder THWoS (The Heavy Weight of Shame)

De vraag is gesteld op 01/06/2010 om 00:20
bron van user
In andere talen...                            


2 antwoorden

stemmen
8

Gebruik een stapel voor de nummers. Doorloop elke rij en controleer de inspringing niveau van elke rij, zonder indrukking wordt niveau 1.

  1. Als het huidige inspringniveau groter is dan de grootte van de stack push zo talrijk is als het verschil is op de stapel (het verschil zou meestal slechts een, maar dit werkt zelfs als iemand zet een kop voor niveau 3 onder een kop van niveau 1, bijvoorbeeld)
  2. Als het huidige inspringniveau kleiner is dan de grootte van de stack, pop en gooi zoveel nummers als het verschil is en dan verhogen de bovenste nummer op de stapel.
  3. Als de huidige inspringniveau gelijk aan de afmeting van de stapel, verhogen het bovenste getal op de stapel

Voor elke rij, het huidige titelnummer de getallen op de stack aaneengeschakeld met een. om ze te scheiden.

Merk op hoe de grootte van de stack handig vertegenwoordigt de vorige regel is inspringniveau.

Voor mensen die vinden het makkelijker om code te lezen, hier is een JavaScript-implementatie voor moderne browsers:

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

antwoordde op 01/06/2010 om 00:33
bron van user

stemmen
2

Dit algoritme neemt aan dat Inspringniveau niet stijgt met meer dan 1 eenheid. Als dat zo is, dan moet je alle "overgeslagen" in te stellen op 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
antwoordde op 01/06/2010 om 00:42
bron van user

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