如何根据值将python字典拆分为多个字典

时间:2018-07-31 09:13:08

标签: python python-3.x dictionary ordereddictionary

我有一个类似的字典:

{'A': [0, 2, 5],
 'B': [1],
 'C': [3, 6, 9],
 'D': [4, 7, 10],
 'E': [8, 11, 13],
 'F': [12]}

,我想根据值列表中连续元素的差异将其拆分为多个词典(例如2)。例如,上面:

dict_2 = {'A': [0, 2],
     'E': [11, 13]}

dict_3 = {'A': [2, 5],
     'C': [3, 6, 9],
     'D': [4, 7, 10],
     'E': [8, 11]}

因此,我比较每个列表中的连续值,如果差异(i+1) - i为2,则将其放入dict_2,如果差异为3,则将其置于dict_3。我忽略了每个列表中只有一个元素或者差异不是2或3的元素。

我正在尝试一种比较繁琐的方法:

def construct_dicts(init_dict, no_jumps=[2,3]):
    dct_2, dct_3 = {}, {}
    for key in init_dict.keys():
        for index in range(len(init_dict[key])):
            if init_dict[key][index+1] - init_dict[key][index] = no_jumps[0]:
                dct_2[key] = [index, index + 1]
            elif init_dict[key][index+1] - init_dict[key][index] = no_jumps[1]:
                dct_3[key] = [index, index + 1]

然而,这麻烦且丑陋(并且尚不起作用)。有没有更Python的方法来做到这一点?

2 个答案:

答案 0 :(得分:1)

这是使用嵌套collections.defaultdict的一般方法:

def categorize_dicts(dictionary):
    dfd = defaultdict(defaultdict)
    for k, v in d.items():
        for i,j in zip(v, v[1:]):
            dfd[j-i].setdefault(k,[]).extend((i, j))
    return dfd  

演示:

In [28]: d = {'A': [0, 2, 5],
        ...:  'B': [1],
        ...:  'C': [3, 6, 9],
        ...:  'D': [4, 7, 10],
        ...:  'E': [8, 11, 13],
        ...:  'F': [12, 15, 17],
        ...:  'T': [19]}
        ...:  

In [29]: categorize_dicts(d)
Out[29]: 
defaultdict(collections.defaultdict,
            {2: defaultdict(None, {'A': [0, 2], 'E': [11, 13], 'F': [15, 17]}),
             3: defaultdict(None,
                         {'A': [2, 5],
                          'C': [3, 6, 6, 9],
                          'D': [4, 7, 7, 10],
                          'E': [8, 11],
                          'F': [12, 15]})})

答案 1 :(得分:1)

您的代码中存在一些问题:

  1. for index in range(len(init_dict[key]))index + 1组合将最终产生IndexError
  2. 您将索引index + 1, index放置在新列表中,而不是相应的列表项中。

此方法旨在解决上述问题并包括一些改进。它适用于任意差异,并使用另一个dict来区分它们。值存储在set中,以防止后续项具有相似差异的重复项。如果不希望这样做,则可以使用list并附加检查。

from collections import defaultdict

d = {
    'A': [0, 2, 5],
    'B': [1],
    'C': [3, 6, 9],
    'D': [4, 7, 10],
    'E': [8, 11, 13],
    'F': [12]
}
diff = defaultdict(lambda: defaultdict(set))

for k, v in d.items():
    for i, j in zip(v, v[1:]):
        diff[j-i][k] |= {i, j}