2016-05-06 5 views
0

私は、Djangoのクエリセットがあります。そのdictsのいくつかのキーが同じ月にある場合、dictsの値を合計するにはどうすればいいですか?

summary = Contracts.objects.all() \ 
        .filter(datestart__gte=time_threshold) \ 
        .values('datestart', 'id_deposits__id_valuta__name') \ 
        .annotate(sum=Sum('suma')) \ 
        .order_by('-id_deposits__id_valuta__name') 

をそして私はで適量をキャッチ:必要に応じてそれは、通貨の合計を更新し

for s in summary: 
    for k, v in CURRENCY.items(): 
     if s['id_deposits__id_valuta__name'] == k: 
      s['sum'] *= CURRENCY[k] 

。それは「datestart」値の月が等しいときdicts

{'sum': Decimal('400000.00'), 'datestart': datetime.date(2016, 3, 1), 'id_deposits__id_valuta__name': 'Гривня'} 
{'sum': Decimal('2500000.00'), 'datestart': datetime.date(2016, 4, 25), 'id_deposits__id_valuta__name': 'Долар'} 
{'sum': Decimal('2500000.00'), 'datestart': datetime.date(2016, 4, 25), 'id_deposits__id_valuta__name': 'Долар'} 

は、今私は、dictsに「合計」キーの値を合計する必要が戻ります。

Ex。いくつかのdictsには、合計、datestartキーがあります。 dictsが同じ月にあるときには、「合計」値の合計を持つ必要があります:2016-04-03,2016-04-14

最小限の方法でこれを行う方法は?

+0

サマリーで 'for s 'を使わないのはなぜでしょうか?s [' sum '] * = CURRENCY.get(s [' id_deposits__id_valuta__name ']、1)'?ここに辞書があり、辞書検索を使用します。 –

+0

@MartijnPieters、私はonelineアルゴリズムのためにあまりスマートではありません)、ご意見ありがとうございます – Oleksiy

+0

「2016-04-03」と「2015-04-05」はどのように扱われるべきですか?それは同じ月ですか(4月とも)ですか、それとも別々にバケツにされるべきですか(2016年4月対2015年4月)? –

答えて

1

辞書を使用して月ごとの合計を追跡します。あなたは初期値を管理するためにここにdefaultdictを使用することができます。

from collections import defaultdict 
from decimal import Decimal 

per_month = defaultdict(Decimal) 

for s in summary: 
    s['sum'] *= CURRENCY.get(s['id_deposits__id_valuta__name'], 1) 
    month = s['datestart'].year, s['datestart'].month 
    per_month[month] += s['sum'] 

私はCURRENCY.items()の上にループを削除しました。代わりにdict.get()を使用して値を取得することができます。キーが辞書にない場合は、代わりに1が使用されます。

(year, month)タプルで合計金額をグループ化しています。異なる年の月を別々の合計として扱うことを前提にしています。

+0

ああ、それは良いアイデアです、試してみます – Oleksiy

2

あなたは月が鍵であり、値がs['sum']あるCounterにすべての辞書を変換し、それらを一緒に追加することができます。

from collections import Counter 

sum((Counter({x['datestart'].month: x['sum']}) for x in summary), Counter()) 
# Counter({4: Decimal('5000000.00'), 3: Decimal('400000.00')}) 

メモ代わりに月と年使用{(x['datestart'].month, x['datestart'].year): x['sum']}を区別する必要がある場合に。

関連する問題