Как создать вложенный словарь из существующего словаря с набором и списком кортежей

Я проанализировал миди-файл и успешно получил словарь нот, разбитых по инструментам. Сокращенный пример этого note_dict ниже, усеченный для целей этого вопроса.

Моя конечная цель состоит в том, чтобы иметь вложенный словарь, который предоставляет мне название дорожки, затем каждую возможную ноту в качестве ключа, а затем список всех возможных следующих нот в качестве значений. Цель состоит в том, чтобы использовать это в качестве цепи Маркова в Foxdot, интерфейсе Python для музыки. поколение.

Это должно выглядеть примерно так:

{'track1': {note: [note1, note2, note3], note2: [note1, note2, note3]}, 'track2': {note: [note1, note2, note3], note2: [note1, note2, note3]}

Вот пример того, что у меня есть:

import itertools 

def pairwise(iterable):
    a, b = itertools.tee(iterable)
    next(b, None)
    return list(zip(a, b))

note_dict = {'Vocal': [-2, -2, -1, -2], 'Guitar': [1, 1, 4, 1, -2, 1]}

note_dict_updated = { track: [{ n for n in notes }, pairwise(notes), notes] for track, notes in note_dict.items() }
print(note_dict_updated)

Это дает мне следующее, где первый набор — это все отдельные заметки, список кортежей — это пара (note, next note), а последний список — это просто необработанный список заметок по порядку.

{'Vocal': [{-2, -1}, [(-2, -2), (-2, -1), (-1, -2)], [-2, -2, -1, -2]], 'Guitar': [{1, 4, -2}, [(1, 1), (1, 4), (4, 1), (1, -2), (-2, 1)], [1, 1, 4, 1, -2, 1]]}

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

Мой желаемый конечный результат, основанный на note_dict выше:

{'Vocal': {-2: [-2, -1], -1: [-2]}, 'Guitar': {1: [1, 4, -2], 4: [1], -2: [1]}}

При этом я не зациклен на методе, где мне нужно работать с note_dict_updated. Если есть более разумный способ перейти от note_dict к желаемому конечному результату, я был бы рад услышать.

edit: я немного обновил свой вопрос. первый ответ работал для моего первоначального примера, но я считаю, что есть проблемы, когда список заметок в каждом значении перекрывается. Надеюсь, мой обновленный желаемый конечный результат будет более полезным.


person Tim    schedule 19.07.2020    source источник


Ответы (1)


Первый цикл создает промежуточный словарь словаря с внутренними ключами и такими же уникальными наборами. Затем это очищается вторым циклом for, как показано здесь:

Вход:

{'Vocal': [-2, -2, -1, -2], 'Guitar': [1, 1, 4, 1]}

Выход:

{'Guitar': {1: [1, 4], 4: [1]}, 'Vocal': {-2: [-1, -2], -1: [-2]}}

Код:

#create a new dictionary of dictionary with inner keys and same unique sets

note_dict_updated={}
for key, value in note_dict.iteritems():
    note_dict_updated[key]={}
    for element in set(note_dict[key]):
        note_dict_updated[key][element]=list(set(note_dict[key]))

# remove the values (of not interest) from list values of inner keys 
for key, value in note_dict_updated.iteritems():
    comb=[]
    for lkey, lvalue in note_dict_updated[key].iteritems():
        for val in lvalue:
            if (val,lkey) in comb:
                try:
                    note_dict_updated[key][lkey].remove(lkey)
                except ValueError as e:
                    print ('Issue in key {} for subkey {}'.format(key,lkey))
        for val in lvalue:
            comb.append((lkey,val))
person Sameeresque    schedule 20.07.2020
comment
Благодарность! При запуске этого для фактического словаря (более 16 тысяч значений) я получаю ValueError: list.remove(x): x not in list Однако ваш код отлично работает с небольшими словарями. Есть ли у вас какие-либо рекомендации, как обойти эту проблему с помощью remove()? - person Tim; 20.07.2020
comment
Я добавил обработчик исключений, который будет печатать оскорбительный ключ и подраздел. Это может помочь вам понять, почему возникает ошибка. - person Sameeresque; 20.07.2020