You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何正确通过循环实现交易金额按年份汇总?

问题描述

我正在编写一个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:40:32