如何添加两个嵌套的python词典?

时间:2018-05-07 09:57:50

标签: python

    a= {u'1009': {u'Avg': 188,
      u'amount_spent': 2820,
      u'size': 15,
      u'users': {u'0': 346041,
       u'1': 658546,
       u'2': 658194,
       u'3': 658316
       }},
    u'1056': {u'Avg': 140,
      u'amount_spent': 140,
      u'size': 1,
      u'users': {u'0': 645767}},
     u'1103': {u'Avg': 95,
      u'amount_spent': 285,
      u'size': 3,
      u'users': {u'0': 339285, u'1': 658440}}
b = {u'1009': {u'Avg': 246.25,
  u'amount_spent': 1970,
  u'size': 8,
  u'users': {u'0': 61496,
   u'1': 1350,
   u'2': 164852,
   u'3': 517760,
   u'4': 576458,
   u'5': 203840,
   u'6': 52239,
   u'7': 516672}},
 u'1056': {u'Avg': 170,
  u'amount_spent': 680,
  u'size': 4,
  u'users': {u'0': 503737, u'1': 624418, u'2': 642471}}}

我有多个嵌套字典,我想通过它们的内部键合并添加,所以我的输出看起来像这样。

c = {u'1009': {u'Avg': 434.25,
  u'amount_spent': 4790,
  u'size': 23,
  u'users': {u'0': 61496,
   u'1': 1350,
   u'2': 164852,
   u'3': 517760,
   u'4': 576458,
   u'5': 203840,
   u'6': 52239,
   u'7': 516672,
   u'8': 346041,
   u'9': 658546,
   u'10': 658194,
   u'11': 658316
}},,,,,

我们的想法是只添加已存在的键的值。如果他们不只是添加新密钥。使用+ opperand添加它们不起作用。我怎么能这样做?

EDIT1: 合并用户密钥的许多问题是由于值本身就是user_id。因此,它们无法添加,而只是附加在用户密钥中。解决此问题的一种方法是将用户键值作为数组:

{u'1009': {u'Avg': 188,
  u'amount_spent': 2820,
  u'size': 15,
  u'users': [346041,
   658546,
   658194,
   658316]},
 u'1056': {u'Avg': 140, u'amount_spent': 140, u'size': 1, u'users': [645767]}

希望这有帮助!

3 个答案:

答案 0 :(得分:1)

这是一个修补的想法,这个递归函数将字典的内容添加到一起。

def add_dict(x, y):
    n = {}
    inter = x.keys() & y.keys()
    outer = (x.keys() | y.keys()) - inter

    for k in x.keys() & y.keys():
        l, r = x[k], y[k]
        if isinstance(l, dict):
            n[k] = add_dict(l, r)
            continue
        n[k] = l + r

    for k in outer:
        l, r = x.get(k), y.get(k)
        if l: n[k] = l
        if r: n[k] = r

    return n

c = add_dict(a, b)

答案 1 :(得分:1)

这是一个递归迭代两个字典的k,v的函数,并对公共密钥的值求和(在字符串总和的情况下要注意结果)。不常见的键也包含在最终字典中,然后返回。

我不确定这是你在寻找什么,因为在你的例子中,一些公共密钥的值被加在一起,而其他公用键则没有。

我希望这对你来说是一个很好的起点。

def merge_dict(dictA, dictB):
    r = {}

    common_k = [k for k in dictA if k in dictB]
    common_k += [k for k in dictB if k in dictA]
    common_k = set(common_k)

    for k, v in dictA.items():
        #add unique k of dictA
        if k not in common_k:
            r[k] = v

        else:
            #add inner keys if they are not containing other dicts 
            if type(v) is not dict:
                if k in dictB:
                    r[k] = v + dictB[k]
            else:
                #recursively merge the inner dicts
                r[k] = merge_dict(dictA[k], dictB[k])

    #add unique k of dictB
    for k, v in dictB.items():
        if k not in common_k:
            r[k] = v

    return r


#test
dictA = {'any key':1, 'point':{'x':2, 'y':3}}
dictB = {'any key':1, 'point':{'x':2, 'y':3, 'z':0, 'even more nested':{'w':99}}, 'extra':8}
merge_dict(dictA, dictB)

{'any key': 2,
 'point': {'x': 4, 'y': 6, 'z': 0, 'even more nested': {'w': 99}},
 'extra': 8}

答案 2 :(得分:-1)

您可以使用字典理解递归:

import itertools
a = {'1009': {'Avg': 188, 'amount_spent': 2820, 'size': 15, 'users': {'0': 346041, '1': 658546, '2': 658194, '3': 658316}}, '1056': {'Avg': 140, 'amount_spent': 140, 'size': 1, 'users': {'0': 645767}}, '1103': {'Avg': 95, 'amount_spent': 285, 'size': 3, 'users': {'0': 339285, '1': 658440}}}
b = {'1009': {'Avg': 246.25, 'amount_spent': 1970, 'size': 8, 'users': {'0': 61496, '1': 1350, '2': 164852, '3': 517760, '4': 576458, '5': 203840, '6': 52239, '7': 516672}}, '1056': {'Avg': 170, 'amount_spent': 680, 'size': 4, 'users': {'0': 503737, '1': 624418, '2': 642471}}}
def full_sum(d1, d2):
  v1 = {a:list(b) for a, b in itertools.groupby(sorted(list(d1.items())+list(d2.items()), key=lambda x:x[0]), key=lambda x:x[0])}
  return {a:sum(_i for h, _i in b) if all(not isinstance(i, dict) for d, i in b) else full_sum(*[i for _, i in b]) for a, b in v1.items()}

def add_dicts(_a, _b):
   return {c:full_sum(d, f) for [c, d], [e, f] in zip(_a.items(), _b.items())}

print(add_dicts(a, b))

输出:

{'1009': {'Avg': 434.25, 'amount_spent': 4790, 'size': 23, 'users': {'0': 407537, '1': 659896, '2': 823046, '3': 1176076, '4': 576458, '5': 203840, '6': 52239, '7': 516672}}, '1056': {'Avg': 310, 'amount_spent': 820, 'size': 5, 'users': {'0': 1149504, '1': 624418, '2': 642471}}}