I have parsed a midi file, and I've successfully gotten a dictionary of notes broken up by instrument. An abbreviated example of this is note_dict
below, truncated for the purposes of this question.
My end goal is to have a nested dictionary that provides me with the track name, then each possible note as a key, then a list of all possible "next" notes as values. The intent is to use this in as a Markov chain in Foxdot, a python interface for music generation.
It should look something like:
{'track1': {note: [note1, note2, note3], note2: [note1, note2, note3]}, 'track2': {note: [note1, note2, note3], note2: [note1, note2, note3]}
Here is an example of what I have:
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)
This gives me the following, where the first set is all distinct notes, the list of tuples is a pairing of (note, next note)
, and the last list is just a raw list of notes in order.
{'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]]}
I'd like the elements of the sets to act as keys, and when the first element of the tuple matches an element of the set, it is added to a list of values associated with the key.
My desired end result, based on note_dict
above is:
{'Vocal': {-2: [-2, -1], -1: [-2]}, 'Guitar': {1: [1, 4, -2], 4: [1], -2: [1]}}
All that said, I am not locked into the method where I need to work with note_dict_updated
. If there is a smarter way to get from note_dict
to my desired end result, I'd love to hear.
edit: I've updated my question a bit. The first answer worked for my initial example, but I believe there are issues when the list of notes in each value overlap. Hopefully, my updated desired end result will be more helpful.
ValueError: list.remove(x): x not in list
Your code works perfectly on small dictionaries, though. Do you have any recommendations to get around this concern withremove()
? – Papuan