【问题标题】:How do I group this list of dicts by the same month? (A follow-up)如何按同一月份对这个字典列表进行分组? (后续)
【发布时间】:2023-04-11 09:52:01
【问题描述】:

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}]

我哪里错了?

【问题讨论】:

    标签: python


    【解决方案1】:

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

    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)}
    

    迭代器和可迭代对象之间的区别可能会让新手有些困惑。我希望我有一个很好的教程来指出这一点……但让我试着解释一下:

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

    iterable 是任何可以进入for 循环、列表理解、生成器表达式等的东西——或者更准确地说,是任何你可以调用iter(foo) 来获得一个iterable 的东西。

    迭代器(通常)也是可迭代的,但反过来不一定正确。特别是,像lists 这样的序列是可迭代的,可以一遍又一遍地为您提供新的迭代器。

    【讨论】:

    • 对我来说仍然有点模糊,但是如果我将其更改为 v = list(v),您的解决方案就可以工作(正如您在文章中解释的那样......可能只是一个错字)
    • @user2312507:我还把for循环改成了for k, group而不是for k, v,所以v = list(group)是对的。但当然你的方式是等价的。
    猜你喜欢
    • 2013-04-17
    • 2022-06-17
    • 2015-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多