基于Python中的常见值合并/连接词典列表

我有两个字典列表(作为Django查询返回).每个字典都有ID值.我想根据ID值将两个合并成一个字典列表.

例如:

list_a = [{'user__name': u'Joe', 'user__id': 1},
          {'user__name': u'Bob', 'user__id': 3}]
list_b = [{'hours_worked': 25, 'user__id': 3},
          {'hours_worked': 40, 'user__id': 1}]

我想要一个函数来产生:

list_c = [{'user__name': u'Joe', 'user__id': 1, 'hours_worked': 40},
          {'user__name': u'Bob', 'user__id': 3, 'hours_worked': 25}]

附加要点:

>列表中的ID可能不是相同的顺序(如上面的示例).
>这些列表可能有相同数量的元素,但是如果它们不是保留来自list_a的所有值(基本上是list_a OUTER JOIN list_b USING user__id),我想要考虑该选项.
>我已经尝试在SQL中这样做,但不可能,因为一些值是基于一些排除的聚合.
>可以肯定的是,由于使用数据库查询,每个列表中最多只能有一个具有相同user__id的字典.

非常感谢你的时间.

最佳答案
我将使用itertools.groupby来分组元素:

lst = sorted(itertools.chain(list_a,list_b), key=lambda x:x['user__id'])
list_c = []
for k,v in itertools.groupby(lst, key=lambda x:x['user__id']):
    d = {}
    for dct in v:
        d.update(dct)
    list_c.append(d)
    #could also do:
    #list_c.append( dict(itertools.chain.from_iterable(dct.items() for dct in v)) )
    #although that might be a little harder to read.

如果你对lambda函数有厌恶,你可以随时使用operator.itemgetter(‘user__id’). (也可能稍微有效)

要使lambda / itemgetter有一点神秘,请注意:

def foo(x):
    return x['user__id']

是与以下任一项相同的东西*

foo = operator.itemgetter('user__id')
foo = lambda x: x['user__id']

*有一些区别,但它们对于这个问题并不重要

转载注明原文:基于Python中的常见值合并/连接词典列表 - 代码日志