В предположении, что последовательность символьных строк представляет нумерацию разделов в схеме, вот возможное решение:
library(data.table)
# reshape to long format
long <- DT[, rn := .I][
, strsplit(No, "[.]"), by = rn][
, V1 := as.integer(V1)][
, lvl := rowid(rn)][]
# find contiguous streaks of rows where there is a gap in levels
nlvl <- long[, .N, keyby = rn][
, gap := cumsum(c(diff(N), 0L) > 1L)][
, M := first(N) + 1L, by = gap]
# non-equi anti-join and recast
long[!nlvl[N > M], on = .(rn, lvl >= M, lvl < N)][
, .(No = paste(V1, collapse = ".")), by = rn]
rn No
1: 1 48.8.1.1
2: 2 48.8.1.2
3: 3 48.8.2
4: 4 48.9
5: 5 48.10
6: 6 48.11
7: 7 48.11.1
8: 8 48.11.1.1
9: 9 48.11.1.2
10: 10 48.11.1.2.1
11: 11 48.11.1.2.2
12: 12 48.11.1.2.3
13: 13 48.11.2
14: 14 48.11.2.1
15: 15 48.11.2.1.1
16: 16 48.11.3
17: 17 48.11.3.1
18: 18 50
Объяснение
Если я правильно понимаю, последовательность строк символов представляет нумерацию разделов в схеме, которая была искажена при вставке ложных дополнительных уровней.ОП ищет метод удаления этих дополнительных уровней.
Итак, давайте предположим некоторые правила нумерации разделов схемы:
- Разрыв в номерах разделов: на том жеуровень, номера разделов всегда увеличиваются на 1.
Например, за разделом 4.1.3
следует либо - *
4.1.4
(переход на уровень 3 раздела) - или
4.2
(если родительский уровень повышен) - или
5
(переход к следующей главе).
- Разрыв в уровнях: дочерний уровень всегда равен 1 уровнюниже уровня родителей.Нумерация разделов на дочернем уровне начинается с 1.
Например, за разделом 4.1.3
может следовать 4.1.3.1
в качестве подраздела, но не на 4.1.3.1.1
, который переходит с уровня раздела 3 на подпод подразделуровень раздела 5.
Поскольку вопрос ОП может быть связан с ситуацией 2, нам нужно идентифицировать строки с пропуском в уровнях относительно предыдущих строк.В качестве исправления все промежуточные избыточные уровни будут удалены.Последний уровень сохраняется, поскольку он предположительно имеет правильную нумерацию.
Первый шаг состоит из добавления номеров строк, разбиения строк символов в "."
, приведения чисел в секции к целому числу и нумерации уровней для каждого из них.строка.Теперь номера разделов представлены в длинном формате:
long
rn V1 lvl
1: 1 48 1
2: 1 8 2
3: 1 1 3
4: 1 1 4
5: 2 48 1
6: 2 8 2
[...]
25: 9 48 1
26: 9 11 2
27: 9 1 3
28: 9 2 4
29: 10 48 1
30: 10 11 2
31: 10 1 3
32: 10 2 4
33: 10 2 5
34: 10 2 6
35: 10 2 7
36: 10 1 8
37: 11 48 1
38: 11 11 2
39: 11 1 3
40: 11 2 4
41: 11 2 5
42: 11 2 6
43: 11 2 7
44: 11 2 8
45: 12 48 1
46: 12 11 2
47: 12 1 3
48: 12 2 4
49: 12 2 5
50: 12 3 6
51: 13 48 1
52: 13 11 2
53: 13 2 3
54: 14 48 1
55: 14 11 2
56: 14 2 3
57: 14 1 4
58: 15 48 1
59: 15 11 2
60: 15 2 3
61: 15 1 4
62: 15 1 5
63: 16 48 1
64: 16 11 2
65: 16 3 3
66: 17 48 1
67: 17 11 2
68: 17 3 3
69: 17 3 4
70: 17 3 5
71: 17 1 6
72: 18 50 1
rn V1 lvl
На следующем шаге идентифицируются непрерывные полосы строк, которые появляются после пробела на уровне раздела.Уровень раздела - это число N
элементов, принадлежащих строке.gap
отмечает все строки, которые появляются после недопустимого перехода на уровне раздела.M
обозначает максимальный уровень раздела, который был бы законным в соответствии с приведенным выше правилом 2.
nlvl
rn N gap M
1: 1 4 0 5
2: 2 4 0 5
3: 3 3 0 5
4: 4 2 0 5
5: 5 2 0 5
6: 6 2 0 5
7: 7 3 0 5
8: 8 4 0 5
9: 9 4 1 5
10: 10 8 1 5
11: 11 8 1 5
12: 12 6 1 5
13: 13 3 1 5
14: 14 4 1 5
15: 15 5 1 5
16: 16 3 2 4
17: 17 6 2 4
18: 18 1 2 4
На последнем этапе дополнительные ложные уровни удаляются из *От 1056 * до неэквивалентного анти-объединения .Затем номера секций воссоздаются путем склеивания частей.
Для сравнения мы можем объединить результат с исходными данными:
long[!nlvl[N > M], on = .(rn, lvl >= M, lvl < N)][
, .(No = paste(V1, collapse = ".")), by = rn][DT, on = "rn"]
rn No i.No
1: 1 48.8.1.1 48.8.1.1.
2: 2 48.8.1.2 48.8.1.2.
3: 3 48.8.2 48.8.2.
4: 4 48.9 48.9.
5: 5 48.10 48.10.
6: 6 48.11 48.11.
7: 7 48.11.1 48.11.1.
8: 8 48.11.1.1 48.11.1.1.
9: 9 48.11.1.2 48.11.1.2.
10: 10 48.11.1.2.1 48.11.1.2.2.2.2.1.
11: 11 48.11.1.2.2 48.11.1.2.2.2.2.2.
12: 12 48.11.1.2.3 48.11.1.2.2.3.
13: 13 48.11.2 48.11.2.
14: 14 48.11.2.1 48.11.2.1.
15: 15 48.11.2.1.1 48.11.2.1.1.
16: 16 48.11.3 48.11.3.
17: 17 48.11.3.1 48.11.3.3.3.1.
18: 18 50 50.
Данные
Расширенная версия данных, публикуемых ОП.
library(data.table)
DT <- data.table(No = c(
"48.8.1.1.",
"48.8.1.2.",
"48.8.2." ,
"48.9." ,
"48.10." ,
"48.11." ,
"48.11.1." ,
"48.11.1.1." ,
"48.11.1.2." ,
"48.11.1.2.2.2.2.1.",
"48.11.1.2.2.2.2.2.",
"48.11.1.2.2.3.",
"48.11.2.",
"48.11.2.1.",
"48.11.2.1.1.",
"48.11.3.",
"48.11.3.3.3.1.",
"50."
))