假设我有一个这样的词典列表:
[{'amount': 42140.0, 'name': 'Payment', 'account_id_credit': 385, 'type': u'expense', 'account_id_debit': 476},
{'amount': 43926.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 641},
{'amount': 3800.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 46330.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 67357.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 323},
{'amount': 26441.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476} ... ]
我想将字典合并在一起,以便关键字“金额”将是amounts
和account_id_credit
相同的字典中所有account_id_debit
的总和,但仅限于{其中{1}}是type
。其他expense
应保持不变。
最好的方法是什么?
答案 0 :(得分:5)
一种方法是创建一个中间字典,由(account_id_credit, account_id_debit)
元组键入,并且总计金额值,然后从中构建聚合字典列表:
ld = [{'amount': 42140.0, 'name': 'Payment', 'account_id_credit': 385, 'type': u'expense', 'account_id_debit': 476},
{'amount': 43926.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 641},
{'amount': 3800.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 46330.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 67357.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 323},
{'amount': 26441.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476} ]
d2 = {}
for d in ld:
if d['type'] != 'expense':
continue
k = (d['account_id_credit'], d['account_id_debit'])
try:
d2[k] += d['amount']
except KeyError:
d2[k] = d['amount']
ld2 = []
for d in ld:
if d['type'] != 'expense':
ld2.append(d)
continue
k = (d['account_id_credit'], d['account_id_debit'])
try:
d['amount'] = d2[k]
# We're done with this amount sum: remove it from the intermediate dict
del d2[k]
except KeyError:
continue
ld2.append(d)
print ld2
[{'account_id_credit': 385, 'account_id_debit': 476, 'amount': 42140.0, 'type': u'expense', 'name': 'Payment'},
{'account_id_credit': 695, 'account_id_debit': 641, 'amount': 43926.0, 'type': u'payable', 'name': 'Payment'},
{'account_id_credit': 695, 'account_id_debit': 476, 'amount': 76571.0, 'type': u'expense', 'name': 'Payment'},
{'account_id_credit': 695, 'account_id_debit': 323, 'amount': 67357.0, 'type': u'payable', 'name': 'Payment'}]
答案 1 :(得分:1)
您可以按这些键聚合词典,并在需要的地方汇总amount
变量。
dicts = [{'amount': 42140.0, 'name': 'Payment', 'account_id_credit': 385, 'type': u'expense', 'account_id_debit': 476},
{'amount': 43926.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 641},
{'amount': 3800.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 46330.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476},
{'amount': 67357.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'payable', 'account_id_debit': 323},
{'amount': 26441.0, 'name': 'Payment', 'account_id_credit': 695, 'type': u'expense', 'account_id_debit': 476}]
def aggregate(dicts, keys):
def worker(aggr, dic):
key_vals = tuple(dic[key] for key in keys)
aggr.setdefault(key_vals, {key: [] for key in dic.iterkeys()})
for key, value in dic.iteritems():
aggr[key_vals][key].append(value)
return aggr
assert len(set(tuple(dic.iterkeys()) for dic in dicts)) == 1
return reduce(worker, dicts, {})
keys = ("account_id_credit", "type", "account_id_debit")
aggr_expense = [dic for keys, dic in aggregate(dicts, keys).iteritems() if keys[1] == u"expense"]
merged_expense = [{key: sum(value) if key == "amount" else value[0] for key, value in dic.iteritems()}
for dic in aggr_expense]
result = merged_expense + filter(lambda dic: dic["type"] != u"expense", dicts)
print(result)
输出:
[{'account_id_credit': 695, 'account_id_debit': 476, 'amount': 76571.0, 'type': u'expense', 'name': 'Payment'},
{'account_id_credit': 385, 'account_id_debit': 476, 'amount': 42140.0, 'type': u'expense', 'name': 'Payment'},
{'account_id_credit': 695, 'account_id_debit': 641, 'amount': 43926.0, 'type': u'payable', 'name': 'Payment'},
{'account_id_credit': 695, 'account_id_debit': 323, 'amount': 67357.0, 'type': u'payable', 'name': 'Payment'}]