Алгоритм - Нумерация по TOC (Оглавление)

голоса
3

Я хочу, чтобы реализовать функцию VBA для нумерации строк Excel на основе глубины группировки ряда.

Но я думаю, что общий алгоритм для генерации КТВ более интересен.

Проблема в:

Учитывая список «зазубренных» линий, таких как

One
 Two
  Three
   Four
 Five
Six

( «Уровень отступа» может быть предполагаются известными и часть входных данных)

Для того, чтобы сгенерировать следующий вывод:

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

Конечно, мой код и работает ..., а также скрытые под THWoS (Тяжелый вес Позора)

Задан 01/06/2010 в 00:20
источник пользователем
На других языках...                            


2 ответов

голоса
8

Используйте стек для чисел. Цикл по каждой строке, и проверить уровень отступа каждой строки, без отступа будучи 1-го уровня.

  1. Если текущий уровень отступа больше, чем размер толчка стеки, как многие из них, как разница в стеке (разница, как правило, только один, но это работает, даже если кто-то ставит заголовок 3-го уровня под 1-го уровня заголовка, например)
  2. Если текущий уровень отступа меньше, чем размер стека, поп и отбросить, как много чисел, как разница, а затем увеличить верхний номер в стеке.
  3. Если текущий уровень отступа равен размеру стека, увеличивать верхнее число в стеке

Для каждой строки, номер текущего названия цифра на стек объединяются вместе с. чтобы отделить их.

Обратите внимание, как размер стека сподручно представляет уровень отступа предыдущей линии.

Для людей, которым легче читать код, вот реализация JavaScript для современных браузеров:

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

Ответил 01/06/2010 в 00:33
источник пользователем

голоса
2

Этот алгоритм предполагает, что уровень отступа никогда не увеличивается более чем на 1 единицу. Если это произойдет, то вы должны установить все «пропущенные» уровни 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
Ответил 01/06/2010 в 00:42
источник пользователем

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