JavaScript基于动态维度将对象数组转换为带汇总的多级父子结构
动态维度层级生成方案
实现逻辑
- 按维度数组的顺序从高到低逐层分组,维度长度可变,自动适配层级数量
- 每个层级节点自动聚合下属所有子节点的销售额总和
- 节点保留当前层级及以上所有维度的属性值,非最低层级新增
children字段存储下一级节点
JavaScript 实现代码
/** * 生成带指标聚合的维度层级树 * @param {Array} rawData 原始分组查询结果数组 * @param {Array} dimensions 维度数组,顺序从高层到低层 * @param {String} metric 要聚合的指标字段名,默认是sales * @returns {Array} 父子结构的层级树 */ function buildDimensionTree(rawData, dimensions, metric = 'sales') { // 递归生成层级 const buildLevel = (data, levelIndex, parentAttrs = {}) => { const currentDim = dimensions[levelIndex]; // 按当前维度分组 const groups = {}; data.forEach(item => { const dimValue = item[currentDim]; if (!groups[dimValue]) groups[dimValue] = []; groups[dimValue].push(item); }); // 生成当前层节点 const levelNodes = []; for (const [dimVal, items] of Object.entries(groups)) { // 聚合当前组的指标总和 const total = items.reduce((sum, item) => sum + item[metric], 0); // 构造当前节点属性:继承上级所有维度属性 + 当前维度属性 + 聚合指标 const node = { ...parentAttrs, [currentDim]: dimVal, [metric]: total }; // 不是最低层级,递归生成子节点 if (levelIndex < dimensions.length - 1) { node.children = buildLevel(items, levelIndex + 1, {...node}); } levelNodes.push(node); } return levelNodes; } return buildLevel(rawData, 0); }
调用示例
// 原始查询结果 const rawData = [ {"state": "S1","city": "CITY1","product": "P1","sales": 1000}, {"state": "S1","city": "CITY2","product": "P1","sales": 2000}, {"state": "S1","city": "CITY1","product": "P2","sales": 2000}, {"state": "S2","city": "CITY1","product": "P1","sales": 1000}, {"state": "S2","city": "CITY2","product": "P1","sales": 2000}, {"state": "S2","city": "CITY2","product": "P2","sales": 2000}, {"state": "S3","city": "CITY1","product": "P2","sales": 1000}, {"state": "S3","city": "CITY2","product": "P2","sales": 2000} ]; // 动态维度数组,可随意增减长度、修改维度顺序 const dimensions = ["state", "city", "product"]; // 生成结果 const result = buildDimensionTree(rawData, dimensions); console.log(JSON.stringify(result, null, 2));
如果需要适配其他语言,核心逻辑完全通用,只需要按对应语言的语法实现分组、递归、聚合三个步骤即可。
内容的提问来源于stack exchange,提问作者Chandrakant Thakkar
相关产品推荐
相关产品推荐

