如何正确通过循环实现交易金额按年份汇总?
问题描述
我正在编写一个getListYear异步函数,原本需返回所有交易的不重复年份列表,目前该功能正常,但还需要为每个返回的年份汇总对应已批准(status_pgm为approved)交易的金额。我尝试了多种嵌套循环的方式但均未成功,以下是我的代码及dbPayments表结构示例,请问实现该需求的最佳方式是什么?
现有代码
public async getListYear(): Promise<any>{ try{ return await client .scan({ TableName: 'dbPayments' }) .promise() .then((response) => { let result = response.Items.filter((e, i) => { return response.Items.findIndex((x) => { return x.date_created.substring(0,4) == e.date_created.substring(0,4) }) == i; }); let years = []; let sum = []; for(let i = 0; i < result.length; i++){ const yearTransaction = new Date(response.Items[i]['date_created']).getFullYear(); years.push(yearTransaction) } // 这里是问题所在,我尝试了如下写法: for(let i = 0; i < response.Items.length; i++){ if(response.Items[i]['status_pgm'] == 'approved'){ for(let i = 0; i < years.length; i++){ let year = new Date(response.Items[i]['date_created']).getFullYear(); let value = 0; if(year == years[i]){ value += response.Items[i]['transaction_amount'] } let data = { years[i]: value } sum.push(data) } } } return { status: 200, list: years, totalSum: sum } }) .catch((error: AxiosError) => { throw error; }) }catch (e) { console.log(e); return {status: 500, msg: "error"} } }
dbPayments表结构示例
id | date_created | transaction_amount | status_pgm 1 2022-10-29T20:54:40.294-04:00 45 approved 2 2022-09-29T20:54:40.294-04:00 30 approved 3 2022-08-29T20:54:40.294-04:00 25 approved 4 2021-10-29T20:54:40.294-04:00 15 approved 5 2021-09-29T20:54:40.294-04:00 10 approved
解决方案
你的代码存在几个核心问题:嵌套循环重复使用变量i导致索引混乱,统计金额时每次重置value为0,最终生成的sum结构也不符合预期。推荐用对象作为统计容器,配合reduce方法一次性完成年份去重和金额汇总,代码更简洁高效。
优化后的代码如下:
public async getListYear(): Promise<any> { try { const response = await client.scan({ TableName: 'dbPayments' }).promise(); // 先过滤出已批准的交易,减少后续处理数据量 const approvedTransactions = response.Items.filter(item => item.status_pgm === 'approved'); // 用reduce遍历统计,同时完成年份去重和金额累加 const yearStats = approvedTransactions.reduce((acc, item) => { const year = new Date(item.date_created).getFullYear(); acc[year] = (acc[year] || 0) + item.transaction_amount; return acc; }, {} as Record<number, number>); // 提取不重复年份列表,可按需求排序 const years = Object.keys(yearStats).map(Number).sort((a, b) => a - b); // 生成符合需求的汇总结构,也可直接返回yearStats对象(键为年份,值为总金额) const totalSum = years.map(year => ({ [year]: yearStats[year] })); return { status: 200, list: years, totalSum: totalSum }; } catch (e) { console.log(e); return { status: 500, msg: "error" }; } }
关键改进点
- 简化逻辑:用
reduce一次遍历完成统计,时间复杂度从O(n²)降到O(n),性能更优。 - 避免变量冲突:不再重复使用循环变量,逻辑更清晰。
- 提前过滤数据:先筛选出已批准的交易,减少后续处理的数据集大小。
- 结构更合理:最终返回的
totalSum是年份与对应金额的数组,符合需求;也可直接返回yearStats对象,使用更灵活。
内容的提问来源于stack exchange,提问作者Clebson
相关产品推荐
相关产品推荐

