python合并列表/元组列表的字典

时间:2013-06-12 15:33:36

标签: python list dictionary

考虑2个字典,

d1 = {'current':    [[1369713600, 29], [1369756800, 47], [1369800000, 34]],
      'curr_total': 110,
      'past':       [[1368417600, 2], [1368460800, 70], [1368504000, 10]],
      'past_total': 82}

d2 = {'current':    [(1369713601, 23), (1369756800, 87), (1369800000, 7)],
      'curr_total': 117,
      'past':       [(1368417600, 100), (1368460800, 7), (1368504000, 9)],
      'past_total': 116}
  • 在第一个词典中,一些值是整数(总计),其他值是列表列表
  • 在第二个字典中,有些值是整数(总数),其他值是元组列表。
  • 在这两个词典中,都有常用的键,例如'current','cure_total'等。
  • 对于两个词典中的相同键,list / tuples的第一个值可以相同或不同。

基于此,我需要一本这样的字典。

f = {'current':    [[1369713600, 29], [1369713601, 23], [1369756800, 134], [1369800000, 41]],
     'curr_total': 227,
     'past':       [[1368417600, 102], [1368460800, 77], [1368504000, 19]],
     'past_total': 198}

我的尝试是:

for i in fo,pl:             
    for j in i:             
        if total.get(j):    
            total[j] += i[j]
        else:               
            total[j] = i[j] 

但是发现,如果第一个值相同,相应列表和元组的第二个值不会聚合?我的方式无论如何都很天真?有人可以建议我更多的pythonic和有效的方法吗?

3 个答案:

答案 0 :(得分:2)

我没有返回'current''past'的列表列表,而是在这里使用dict,因为对于这种情况,它是更合适的数据结构。

如果您仍然希望他们返回列表,那么您可以使用total['current'].items()total['past'].items()

from itertools import chain
d1 = {'current':    [[1369713600, 29], [1369756800, 47], [1369800000, 34]],
      'curr_total': 110,
      'past':       [[1368417600, 2], [1368460800, 70], [1368504000, 10]],
      'past_total': 82}

d2 = {'current':    [(1369713601, 23), (1369756800, 87), (1369800000, 7)],
      'curr_total': 117,
      'past':       [(1368417600, 100), (1368460800, 7), (1368504000, 9)],
      'past_total': 116}

total  = {}
for k,v in chain(d1.iteritems() ,d2.iteritems()):
    if isinstance(v, list):
        for k1, v1 in v:
            dic = total.setdefault(k,{})
            dic[k1] = dic.get(k1,0) + v1
    else:
        total[k] = total.get(k,0) + v

#convert the dicts to list
for k in total:
    if isinstance(total[k], dict):
        total[k] = total[k].items()
print total        

<强>输出:

{'current': [(1369713600, 29), (1369756800, 134), (1369800000, 41), (1369713601, 23)],
 'past': [(1368417600, 102), (1368460800, 77), (1368504000, 19)],
 'curr_total': 227,
 'past_total': 198
}

答案 1 :(得分:1)

for i in fo,pl:             
    for j in i:             
        if total.get(j):    
            total[j] += i[j]
        else:               
            total[j] = i[j] 

是一个良好的开端,但正如您所指出的,您最终会得到以下列表:

f['current'] = [[1369713600, 29], [1369756800, 47], [1369800000, 34], (1369713601, 23), (1369756800, 87), (1369800000, 7)]

这样的清单减少了:

l = map(list, f['current'])
res = []
for k, v in groupby(sorted(l), lambda x: x[0]):
    res.append([k, sum(map(lambda x: x[1], v))])

答案 2 :(得分:0)

这样的事情应该有效

d1 = {'current':    [[1369713600, 29], [1369756800, 47], [1369800000, 34]],
    'curr_total': 110,
    'past':       [[1368417600, 2], [1368460800, 70], [1368504000, 10]],
    'past_total': 82}

d2 = {'current':    [(1369713601, 23), (1369756800, 87), (1369800000, 7)],
    'curr_total': 117,
    'past':       [(1368417600, 100), (1368460800, 7), (1368504000, 9)],
    'past_total': 116}

def merge_dicts(d1, d2):
    d = dict()
    for key, val in d1.items():
        if key in d2:
            try:
                val1 = dict(val)
                val2 = dict(d2[key])
                d[key] = merge_dicts(val1, val2).items()
            except TypeError:
                d[key] = val + d2[key]
        else:
            d[key] = val
    return d

merge_dicts(d1, d2)

<强>输出:

{'curr_total': 227,
 'current': [(1369713600, 29), (1369756800, 134), (1369800000, 41)],
 'past': [(1368417600, 102), (1368460800, 77), (1368504000, 19)],
 'past_total': 198}