如何从现有字典中使用元组的集合和列表创建嵌套字典

7
我已经解析了一个midi文件,并成功得到了按乐器分隔的音符字典。以下是一个缩略版的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)

这给了我以下结果,其中第一组是所有不同的音符,元组列表是(音符,下一个音符)的配对,最后一个列表只是按顺序排列的原始音符列表。
{'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得到我想要的最终结果,我很乐意听取建议。

编辑:我稍微更新了我的问题。第一个答案对于我的初始示例起作用,但我相信每个值中的笔记列表重叠时会出现问题。希望我的更新后的期望结果能更有帮助。

1个回答

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

当在实际字典上运行此代码(超过16k个值),我会得到以下错误: ValueError: list.remove(x): x not in list但是,您的代码在小型字典上运行得非常完美。您有什么建议可以解决remove()这个问题吗? - Tim
我已经添加了一个异常处理程序,它将打印出有问题的键和子键。这可能会帮助您确定错误的原因。 - Sameeresque

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接