Algorithme - Numérotation de TOC (Table des matières)

voix
3

Je veux mettre en œuvre une fonction VBA pour nombre de lignes Excel en fonction de la profondeur de regroupement de la ligne.

Mais je pense qu'un algorithme général pour générer TOCs est plus intéressant.

Le problème est:

Étant donné une liste de lignes « en retrait » telles que

One
 Two
  Three
   Four
 Five
Six

(Le « niveau d'indentation » peut être supposée connue et une partie des données d'entrée)

Pour générer la sortie suivante:

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

Bien sûr, mon code est en cours d'exécution et ... et aussi caché sous THWoS (Le poids lourd de la honte)

Créé 01/06/2010 à 00:20
source utilisateur
Dans d'autres langues...                            


2 réponses

voix
8

Utiliser une pile pour les nombres. Boucle dans chaque rangée, et vérifier le niveau d'indentation de chaque rangée, sans indentation étant de niveau 1.

  1. Si le niveau de retrait actuel est supérieur à la taille de la poussée de la pile autant de ceux que la différence est sur la pile (la différence serait généralement un, mais cela fonctionne même si quelqu'un met un titre de niveau 3 sous un titre de niveau 1, par exemple)
  2. Si le niveau de retrait en cours est inférieure à la taille de la pile, pop et défausser autant de chiffres que la différence est puis incrémenter le nombre supérieur sur la pile.
  3. Si le niveau de retrait actuel est égale à la taille de la pile, incrémenter le nombre supérieur de la pile

Pour chaque ligne, le numéro du titre en cours est les chiffres sur la pile concaténés avec. pour les séparer.

Notez comment la taille de la pile représente haut la main le niveau de retrait de la ligne précédente.

Pour les personnes qui trouvent plus facile à lire le code, voici une implémentation JavaScript pour les navigateurs modernes:

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

Créé 01/06/2010 à 00:33
source utilisateur

voix
2

Cet algorithme suppose que le niveau d'indentation augmente jamais de plus de 1 unité. Dans le cas contraire, vous devez définir tous les niveaux « sautées » 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
Créé 01/06/2010 à 00:42
source utilisateur

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