Как хранить информацию об иерархии во вложенной структуре

Надеюсь, у вас все отлично!

Ниже приведена выдержка из документа в файле .TXT. Я хочу прочитать текстовый файл со следующим содержимым:

1 Main Heading 1
1.1 Sub-heading 1
1.2 Sub-heading 2
2 Main Heading 2
2.1 Sub-heading 1
2.1.1 Sub-Sub-heading 1
2.1.2 Sub-Sub-heading 2

После прочтения я хочу ДИНАМИЧЕСКИ сохранить его в словаре Python, то есть во вложенных списках, как показано ниже:

{"file name": { "Main Heading 1": { "Sub-heading 1" : [], "Sub-heading 2" : [] }},
              { "Main Heading 2": { "Sub-heading 1": [ "Sub-Sub-heading 1", "Sub-Sub-heading 2" ] } } }

Вышеуказанное не является фиксированной структурой и может быть динамической с различными файлами, и я буду дополнительно автоматизировать процесс в цикле. Я новичок во вложенном словаре и застрял на этапе преобразования файла .txt -> JSON. Любая помощь в этом отношении будет очень полезной. Спасибо!!


person Terminator    schedule 22.01.2021    source источник
comment
Будет ли это всегда до 3 уровней? Также ваша структура непоследовательна - почему, когда нет подзаголовка, подзаголовок находится в списке, а не в dict с пустыми списками для подзаголовков?   -  person buran    schedule 22.01.2021
comment
1. Максимум до 3 уровней, да. 2. Предложенная вами структура также будет работать для меня ... отредактировал то же самое в вопросе. Пожалуйста, дайте мне знать ваши предложения.   -  person Terminator    schedule 22.01.2021


Ответы (1)


import json

toc = """1 Main Heading 1
1.1 Sub-heading 1
1.2 Sub-heading 2
2 Main Heading 2
2.1 Sub-heading 1
2.1.1 Sub-Sub-heading 1
2.1.2 Sub-Sub-heading 2"""

myfile = 'myfile'

data = {myfile:{}}
for line in toc.splitlines():
    levels, title = line.split(' ', maxsplit=1)
    levels = levels.rstrip('.').split('.')
    if len(levels) == 1:
        heading = title
        data[myfile][heading] = {}
    elif len(levels) == 2:
        sub_heading = title
        data[myfile][heading][sub_heading] = []
    if len(levels) == 3:
        data[myfile][heading][sub_heading].append(title)

print(json.dumps(data, indent=4))

выход

{
    "myfile": {
        "Main Heading 1": {
            "Sub-heading 1": [],
            "Sub-heading 2": []
        },
        "Main Heading 2": {
            "Sub-heading 1": [
                "Sub-Sub-heading 1",
                "Sub-Sub-heading 2"
            ]
        }
    }
}
person buran    schedule 22.01.2021
comment
Чистый и блестящий код, приятель. Работал как шарм! Это работает для всех, кроме случаев, когда номер заголовка заканчивается точкой, т. е. 1. XYZ, 2.1. ABC, который я пытался удалить с помощью replace(), но не работал, не затрагивая другие точки. Какие-либо предложения? Кроме того, есть ли способ обрабатывать случаи, когда есть переходы, например, с 1 на 1.1.1 вместо 1 на 1.1, а затем на 1.1.1. - person Terminator; 22.01.2021
comment
вы всегда можете .rstrip('.')` удалить конечную точку, если она присутствует. я отредактировал свой ответ - person buran; 22.01.2021
comment
Всегда есть способ справиться с разными случаями, но то, что вы описываете 1 -> 1.1.1, не имеет смысла. Это предполагает неправильную структуру - person buran; 22.01.2021
comment
Спасибо, rstrip заработал. Что касается 1 -> 1.1.1, я знаю, что это нелогично, но, к сожалению, вывод текста происходит из PDF-документов с OCR. Нужно будет как-то справиться с этим, отредактировав 1.1.1 до 1.1, но не уверен, как работает сравнение двух строк в одном и том же txt, учитывая, что мы анализируем файл построчно. - person Terminator; 22.01.2021