如何在同一个月对这个dicts列表进行分组? (后续)

时间:2013-04-23 19:27:45

标签: python

just asked a very similar question here并且两个答案都有效。但是,当我有>每个字典中有2个字典键,第3个键的值总是为0.例如:

myList = [{'date':'2008-04-23','value':'1','value2':'2'}, {'date':'2008-04-01','value':'8','value2':'5'}, {'date':'2008-04-05','value':'3','value2':'4'}, {'date':'2009-04-19','value':'5','value2':'1'}, {'date':'2009-04-21','value':'8','value2':'1'},{'date':'2010-09-09','value':'3','value2':'1'},
    {'date':'2010-09-10','value':'4','value2':'9'},
    ]

mgilson答案的修改版本:

import itertools
from itertools import groupby
myList.sort(key=lambda x:x['date'][:7])
for k,v in groupby(myList,key=lambda x:x['date'][:7]):
    print k, list(v)
for k,v in groupby(myList,key=lambda x:x['date'][:7]):
    print {'date':k+'-01','value':sum(int(d['value']) for d in v),'value2':sum(int(d['value2']) for d in v)}

结果:

{'date': '2008-04-01', 'value2': 0, 'value': 12}
{'date': '2009-04-01', 'value2': 0, 'value': 13}
{'date': '2010-09-01', 'value2': 0, 'value': 7}

Pavel答案的修改版本:

import itertools
key = lambda datum: datum['date'].rsplit('-', 1)[0]
myList.sort(key=key)
result = [{
            'date': key + '-01',
            'value': sum(int(item['value']) for item in group),
            'value2': sum(int(item['value2']) for item in group)
           } for key, group in itertools.groupby(myList, key=key)]

print result

结果:

[{'date': '2008-04-01', 'value2': 0, 'value': 12}, {'date': '2009-04-01', 'value2': 0, 'value': 13}, {'date': '2010-09-01', 'value2': 0, 'value': 7}]

我在哪里错了?

1 个答案:

答案 0 :(得分:4)

问题在于您尝试使用相同的迭代器两次:

print {'date':k+'-01','value':sum(int(d['value']) for d in v),'value2':sum(int(d['value2']) for d in v)}

第一次调用sum会消耗一个消耗所有v的生成器表达式。对sum的第二次调用会消耗一个生成器表达式,该表达式会消耗v中剩下的任何内容,这是......没有。

有几种不同的方法可以解决这个问题,但最小的变化就是将v变成list并改为使用它:

for k, group in groupby(myList,key=lambda x:x['date'][:7]):
    v = list(group)
    print {'date':k+'-01','value':sum(int(d['value']) for d in v),'value2':sum(int(d['value2']) for d in v)}

迭代器和迭代器之间的区别对于新手来说可能有点混乱。我希望我有一个很好的教程指出这个......但是让我试着解释一下:

迭代器是你只能迭代一次的东西。

可迭代是可以进入for循环,列表推导,生成器表达式等的任何东西 - 或者更确切地说,任何可以调用iter(foo)以获得可迭代的东西。

迭代器(通常)也是迭代的,但反过来不一定是真的。特别是,像list s这样的序列是迭代的,可以反复给你一个新的迭代器。