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

JavaScript实现二维数组动态表头分组聚合(支持sum等操作)

高效实现动态分组聚合函数GenerateGroupByData

针对你提出的需求,我整理了一个简洁高效的实现方案——核心思路是用对象作为分组映射表,通过一次遍历完成分组和聚合,同时完美支持动态分组字段和多种聚合操作。

完整实现(JavaScript)

const sqlData = [ ['a','b','c','d','e','f','g'], ['aa','10/11/2020','##',2,3,4,5], ['bb','10/12/2020','$$',23,13,14,95], ['aa','10/12/2020','!!',21,23,24,58], ['aa','10/12/2020','##',22,13,44,55], ['aa','10/11/2020','$$',12,33,45,52], ['bb','10/11/2020','!!',52,32,49,52], ['aa','10/11/2020','!!',72,53,44,51], ['bb','10/11/2020','##',12,3,43,65], ['bb','10/13/2020','##',112,63,4,85], ['bb','10/13/2020','$$',22,63,24,95], ['bb','10/12/2020','$$',32,73,44,50], ['bb','10/13/2020','$$',52,388,24,50], ['bb','10/13/2020','$$',72,233,41,52], ['bb','10/13/2020','##',82,123,46,57], ['bb','10/13/2020','!!',92,763,47,58], ];

function GenerateGroupByData(CurrentData, groupbyheaders, ops = 'sum') {
    // 拆分表头和数据行
    const [headers, ...rows] = CurrentData;
    
    // 获取分组字段的索引,以及需要聚合的字段索引
    const groupIndices = groupbyheaders.map(header => headers.indexOf(header));
    const aggregateIndices = headers
        .map((_, idx) => groupbyheaders.includes(headers[idx]) ? null : idx)
        .filter(idx => idx !== null);
    
    // 定义聚合操作字典,方便快速调用和扩展
    const aggregateOps = {
        sum: (acc, val) => acc + val,
        average: (acc, val, count) => (acc * (count - 1) + val) / count,
        max: (acc, val) => Math.max(acc, val),
        min: (acc, val) => Math.min(acc, val)
    };

    // 兜底:如果传入的操作不存在,默认用sum
    const activeOp = aggregateOps[ops] || aggregateOps.sum;

    // 一次遍历完成分组聚合
    const groups = rows.reduce((acc, row) => {
        // 生成唯一分组键:用特殊分隔符拼接分组字段值,避免冲突
        const groupKey = groupIndices.map(idx => row[idx]).join('|');
        
        if (!acc[groupKey]) {
            // 初始化分组数据:保存分组字段值,聚合字段初始化为当前行的值
            acc[groupKey] = {
                groupValues: groupIndices.map(idx => row[idx]),
                aggregates: aggregateIndices.map(idx => row[idx]),
                count: 1 // 用于平均值计算的计数
            };
        } else {
            // 更新聚合字段
            acc[groupKey].aggregates = acc[groupKey].aggregates.map((currVal, aggIdx) => {
                const rowVal = row[aggregateIndices[aggIdx]];
                return activeOp(currVal, rowVal, acc[groupKey].count + 1);
            });
            acc[groupKey].count++;
        }
        return acc;
    }, {});

    // 转换为要求的二维数组格式
    const resultHeaders = [...groupbyheaders, ...headers.filter(h => !groupbyheaders.includes(h))];
    const resultRows = Object.values(groups).map(group => [...group.groupValues, ...group.aggregates]);

    return [resultHeaders, ...resultRows];
}

// 示例调用:按a、b分组求和
console.log(GenerateGroupByData(sqlData, ['a', 'b']));
// 示例调用:按a、c分组求平均值
console.log(GenerateGroupByData(sqlData, ['a', 'c'], 'average'));

核心亮点说明

  1. 高效低复杂度:只用一次reduce遍历数据行,时间复杂度为O(n)(n是数据行数),比多次遍历的方案性能好很多
  2. 完全动态适配:不管你传入哪些分组字段,都会自动从表头匹配索引,不需要硬编码字段位置
  3. 易扩展聚合操作:如果需要新增聚合逻辑(比如count、median),直接在aggregateOps字典里加对应函数即可
  4. 鲁棒性处理:如果传入了不支持的聚合操作,会自动兜底用sum;若要更严谨,还可以加分组字段存在性校验
  5. 分组键唯一性:用|作为分隔符拼接分组值,如果你担心字段值里包含|,可以换成\u0000这种不可见字符,避免键冲突

内容的提问来源于stack exchange,提问作者Shivam Sahil

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.09 13:52:44