提问人:Mav 提问时间:12/16/2011 最后编辑:ggorlenMav 更新时间:6/9/2021 访问量:1328
字典列表的运行总计
Running total for list of dict
问:
有一个 dict 的 python 列表,如下所示:
Dict1 = [{'date': 1, 'name': 'xyz', 'qty': 100},
{'date': 1, 'name': 'xyz', 'qty': 200},
{'date': 1, 'name': 'xyz', 'qty': 300},
{'date': 1, 'name': 'xyz2', 'qty': 30},
{'date': 2, 'name': 'xyz', 'qty': 1000},
{'date': 2, 'name': 'xyz2', 'qty': 300},
{'date': 3, 'name': 'xyz', 'qty': 500},
{'date': 3, 'name': 'xyz2', 'qty': 500},
{'date': 3, 'name': 'xyz3', 'qty': 500},
{'date': 3, 'name': 'xyz', 'qty': 600}]
想要获得每个日期的每个名称的运行总数:
date:1,name:xyz,qty:600
date:1,name:xyz2,qty:30
date:2,name:xyz,qty:1600
date:2,name:xyz2,qty:330
date:3,name:xyz,qty:2700
date:3,name:xyz2,qty:830
date:3,name:xyz3,qty:500
谢谢。
答:
4赞
Acorn
12/16/2011
#1
from itertools import groupby
from operator import itemgetter
for k, gr in groupby(Dict1, key=itemgetter('date', 'name')):
print "date:%i,name:%s,qty:%i" % (k[0], k[1], sum(d['qty'] for d in gr))
评论
0赞
Mav
12/16/2011
这并不能提供跨日期的运行总数。
0赞
Acorn
12/16/2011
我不确定你在找什么。你能解释一下吗?
0赞
Karl Knechtel
12/16/2011
OP 中描述的输出也不是“运行总计”;每个(日期、名称)组合各相加。
0赞
ggorlen
6/9/2021
请注意,如果组尚未排序为列表中的相邻组,则将失败,从而生成额外的块。loop 和 defaultdict
更可靠,因为不需要对输入列表进行排序,而不会影响优雅性或时间复杂性。groupby
0赞
Zach Kelling
12/16/2011
#2
保持运行总数的一个简单方法是使用 collections.defaultdict
:
from collections import defaultdict
totals = defaultdict(int)
for d in Dict1:
name = d['name']
# increment total
totals[name] += d['qty']
print 'date:%s,name:%s,qty:%d' % (d['date'], name, totals[name])
评论
0赞
Felix Yan
12/16/2011
您可能遗漏了问题:)中的部分for each date
0赞
Zach Kelling
12/16/2011
从他的预期输出来看,似乎实际上并没有考虑日期。
0赞
vsvasya
12/16/2011
#3
我只找到了一些复杂的方法:
items = {}
for item in Dict1:
key = (item['date'], item['name'])
items.setdefault(key, 0)
items[key] += item['qty']
Dict2 = sorted([dict(date=key[0], name=key[1], qty=qty) for key, qty in items.items()],
key=labmda x: (x['date', x['name']))
0赞
Fei
12/16/2011
#4
result = {}
for date, name in [ (d['date'], d['name']) for d in Dict1]:
result[(date, name)] = sum( [ d['qty'] for d in Dict1 if d['date'] <= date and d['name'] == name] )
keys = result.keys()
keys.sort()
for key in keys:
print "date:%d, name:%s, qty:%d"%(key[0], key[-1], result[key])
1赞
yosukesabai
12/16/2011
#5
我以为日期是增加订单。
# store values
tot = {}
# the last date
date0 = Dict1[-1]['date']
# easier to work from back, i found
for line in Dict1[-1::-1]:
date, name, qty = [line[x] for x in 'date', 'name', 'qty']
# add the value to all subsequent days
for d in range(date, date0+1):
tot.setdefault(d, {}).setdefault(name, [0])[0] += qty
# i was putting value into array, and i put it out into a scalar
tot = dict((k, dict((kk,vv[0]) for kk,vv in v.items())) for k,v in tot.items())
print tot
结果:
{1: {'xyz': 600, 'xyz2': 30}, 2: {'xyz': 1600, 'xyz2': 330}, 3: {'xyz': 2700, 'xyz3': 500, 'xyz2': 830}}
评论
0赞
Mav
12/19/2011
现在,我在实际的日期时间对象中拥有日期。请帮忙。
0赞
yosukesabai
12/19/2011
减去两个 DateTime 对象得到 TimeDelta 对象,该对象具有 .days 属性。它告诉您两个日期时间之间的天数。还可以将 TimeDelta 对象添加/减去 DateTime 对象。例如。明天 = datetime.datetime.now() + datetime.timedelta(days=1)。我会将所有日期转换为您的组合的序列日期数(从您选择的某一天开始有多少天),以使数学更容易
评论