Правильное размещение элементов списка во вложенном словаре

#python

Вопрос:

У меня есть список текстовых блоков, подобных этому:

 blocks = [
    "created may 27th", 
    "Introduction Foo Bar Bar", 
    "Lorem te Ipsum", 
    "Method Participants Foo Foo Bar Procedure Baz"
]
 

И следующий словарь:

 structure = {
    "text": [],
    "Introduction" : {
        "text": []
    },
    "Method": {
        "Participants" : {
            "text": []
        },
        "Procedure": {
            "text": []
        }
    }
}
 

Я хочу объединить их так, чтобы текстовые блоки оказывались в правильном месте в зависимости от порядка присутствия и возможных строк заголовка в их начале, чтобы создать следующую структуру:

 structure = {
    "text": ["created may 27th"]
    "Introduction" : {
        "text": ["Foo Bar Bar", "Lorem te Ipsum"]
    }
    "Method": {
        "Participants" {
            "text": ["Foo Foo Bar"]
        },
        "Procedure": {
            "text": ["Baz"]
        }
}
 

Это должно работать для списка любой длины, а также для словаря любой глубины.

Моя интуиция подсказала мне пройтись по текстовому блоку , а затем рекурсивно найти его местоположение, проверив, если block.startswith(header) , если это так, разделив заголовок и повторив с правильным разделением текстового блока, и в противном случае добавив к выбранному в данный момент значению «текст». Самая большая проблема для меня-это 2 цикла для обхода текстовых блоков и элементов словаря, при этом отслеживая местоположение в словаре и имея возможность перейти к следующему элементу, когда это означает возврат в дерево.

Это то, что я пробовал:

 def add_block(block, current_section, header_index=0):
    header = list(current_section.keys())[header_index]
    if not block.strip().startswith(header):
        current_section['text'].append(block)
    elif block.startswith(header):
        block = block.partition(header)[-1]
        add_block(block, current_section[header], header_index 1)    

for block in blocks:
    add_block(block, structure)
 

Комментарии:

1. Всегда ли список «блоков» состоит из 4 записей, или введение может охватывать несколько записей списка? (а не только эти двое)?

2. @Amiga500 глубина и длина как ключей словаря, так и элементов списка не ограничены.

3. имеют ли значение теги /n, или вы можете работать без них

4. сначала извлеките все ключи из всех глубин словаря, затем манипулируйте блоками в соответствии с..соедините все элементы в блоке и выполните манипуляцию строками… это должно сработать

5. @sadbro, к сожалению, это не учитывает дубликаты ключей, появляющихся на разных уровнях словаря.

Ответ №1:

Учитывая неограниченную длину ключей/элементов, возможно, лучше всего разбить список «блоков» на подсписки, прежде чем пытаться назначить в структуру.

 subLists = {'text':[], 'intro':[], 'method':[]}

posits = ["text", "intro", "method"]
positSwitches = ['Introduction', 'Method', "###"]  #Last entry is just an impossible string so we don't go out of range.
iPosits = 0
for line in blocks:
    if left(line[:len(positSwitches[iPosits)] == positSwitches[iPosits]:
        #We are at first line of a new entry, i.e. moving from text to intro
        iPosits = iPosits   1
     
    subLists[posits[iPosits]].append(line)
 

Вышесказанное должно дать нам словарь, который разбивает список «блоков» на 3 списка для каждого элемента. Исходя из этого, вы можете назначить отдельные функции для заполнения структуры. К сожалению, непроверено, и мне придется бежать — но, надеюсь, это основа для работы!