繁体   English   中英

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

[英]python merging dictionary of lists of lists/tuples

考虑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”等等。
  • 对于两个字典中的相同键,列表/元组的第一个值可以相同或相反。

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

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] 

但是发现,如果第一个值相同,则对应的列表和元组的第二个值不会汇总? 我的方式很幼稚吗? 有人可以建议我使用更有效的Python方式吗?

我没有在此处返回'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
}
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))])

这样的事情应该工作

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}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM