将这个Python结构的值合并为单个字典的更快捷方法是什么?

时间:2010-03-12 13:34:37

标签: python data-structures refactoring performance

我已经重构了下面的合并字典(all_classes)是如何创建的,但我想知道它是否更有效率。

我有一本字典词典,如下:

groups_and_classes = {'group_1': {'class_A': [1, 2, 3],
                                  'class_B': [1, 3, 5, 7], 
                                  'class_c': [1, 2], # ...many more items like this
                                 },
                      'group_2': {'class_A': [11, 12, 13],
                                  'class_C': [5, 6, 7, 8, 9]
                                 }, # ...and many more items like this
                     }

一个函数从groups_and_classes创建一个新对象(经常调用创建它的函数):

all_classes = {'class_A': [1, 2, 3, 11, 12, 13],
               'class_B': [1, 3, 5, 7, 9],
               'class_C': [1, 2, 5, 6, 7, 8, 9]
              }

现在,有一个循环可以做到这一点:

all_classes = {}
for group in groups_and_classes.values():
    for c, vals in group.iteritems():
        for v in vals:
            if all_classes.has_key(c):
                if v not in all_classes[c]:
                    all_classes[c].append(v)
            else:
                all_classes[c] = [v]

到目前为止,我将代码更改为使用set而不是list,因为列表的顺序无关紧要值必须是唯一的:

all_classes = {}
for group in groups_and_classes.values():
    for c, vals in group.iteritems():
        try:
            all_classes[c].update(set(vals))
        except KeyError:
            all_classes[c] = set(vals)

这有点好,我没有必要将集转换为列表,因为代码中使用了all_classes

问题:是否有更有效的方法来创建all_classes(除了在构建groups_and_classes的同时构建它,并且在任何地方都会调用此函数) ?

3 个答案:

答案 0 :(得分:4)

这是一个简洁的调整,虽然我不确定性能:

from collections import defaultdict
all_classes = defaultdict(set)
for group in groups_and_classes.values():
    for c, vals in group.iteritems():
        all_classes[c].update(set(vals))

自切片面包以来,默认食品并不是最好的,但它们非常酷。 :)

答案 1 :(得分:2)

可能会稍微改善一点的一件事是避免冗余转换为集合,只需使用:

all_classes[c].update(vals)

update实际上可以采用任意迭代,因为它基本上只是迭代和添加,因此您可以避免额外的转换步骤。

答案 2 :(得分:2)

Combining Dictionaries Of Lists In Python

def merge_dols(dol1, dol2):
    result = dict(dol1, **dol2)
    result.update((k, dol1[k] + dol2[k]) for k in set(dol1).intersection(dol2))
    return result

g1 = groups_and_classes['group_1']
g2 = groups_and_classes['group_2']

all_classes = merge_dols(g1,g2)
  

OR

all_classes = reduce(merge_dols,groups_and_classes.values())

- 从Alex Martelli

复制

如果您获得两个以上的论坛,则可以使用itertools.reduce

all_classes = reduce(merge_dols,groups_and_classes.values())