简体   繁体   English

如何从具有元组集和列表的现有字典创建嵌套字典

[英]How to create a nested dictionary from existing dictionary with set and list of tuples

I have parsed a midi file, and I've successfully gotten a dictionary of notes broken up by instrument.我已经解析了一个 midi 文件,并且我已经成功地得到了一个按乐器分解的音符字典。 An abbreviated example of this is note_dict below, truncated for the purposes of this question.一个简短的例子是下面的note_dict ,为了这个问题的目的而被截断。

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.目的是将其用作Foxdot 中的马尔可夫链,这是一个用于音乐生成的 python 接口。

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.这给了我以下内容,其中第一组是所有不同的音符,元组列表是(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]]}

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:根据上面的note_dict ,我想要的最终结果是:

{'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 .尽管如此,我并没有被锁定在我需要使用note_dict_updated的方法中。 If there is a smarter way to get from note_dict to my desired end result, I'd love to hear.如果有更聪明的方法可以从note_dict获得我想要的最终结果,我很想听听。

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.希望我更新后的预期最终结果会更有帮助。

The first loop creates an intermediary dictionary of dictionary with inner keys and the same unique sets.第一个循环创建具有内部键和相同唯一集的字典的中间字典。 This is then cleaned with a second a for-loop as shown here:然后使用第二个 for 循环对其进行清理,如下所示:

Input:输入:

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

Output: Output:

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

Code:代码:

#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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM