求助:基于jQuery实现按Rank分组统计的高效数组生成方案
高性能实现按Rank分组统计的jQuery方案
嘿,我来帮你解决这个分组统计的性能问题!先理清楚你的需求和当前遇到的困境:
你的需求
你有一组存储在jQuery对象中的数据,结构如下:
| Group | Rank | Value |
|---|---|---|
| A | 1 | 200 |
| B | 2 | 200 |
| C | 3 | 200 |
| D | 3 | 500 |
| E | 3 | 600 |
| F | 3 | 400 |
| G | 4 | 100 |
| H | 4 | 300 |
你需要生成一个按Rank分组的数组,包含每个Rank的总和、行数统计:
var groupsArray = [ { "Rank" : 1, "Total": 200, "TotalRows": 1 }, { "Rank" : 2, "Total": 200, "TotalRows": 1 }, { "Rank" : 3, "Total": 1700, "TotalRows": 4 }, { "Rank" : 4, "Total": 400, "TotalRows": 2 } ];
你之前尝试的嵌套for循环是O(n²)的时间复杂度,数据量越大性能越差,这确实不是最优解。
高性能解决方案
我们可以用单次遍历+临时映射对象的方式,把时间复杂度降到O(n),这是处理这类分组统计问题的标准高效方案:
代码实现
var groupsArray = []; // 创建一个临时映射对象,用来缓存每个Rank的统计数据 var rankStatsMap = {}; // 只用一次each遍历所有数据 $(ds.data).each(function() { const currentRank = this.GridCell.Rank; const currentValue = parseInt(this.GridCell.Value, 10); // 确保是数字类型,避免字符串拼接 // 如果当前Rank还没被记录,初始化统计对象 if (!rankStatsMap[currentRank]) { rankStatsMap[currentRank] = { Rank: currentRank, Total: 0, TotalRows: 0 }; } // 更新当前Rank的统计值 rankStatsMap[currentRank].Total += currentValue; rankStatsMap[currentRank].TotalRows += 1; }); // 把映射对象转换为目标数组 for (const rankKey in rankStatsMap) { if (rankStatsMap.hasOwnProperty(rankKey)) { groupsArray.push(rankStatsMap[rankKey]); } } // 可选:如果需要严格按Rank升序排列(对象键的遍历顺序在现代浏览器中是数字升序,但保险起见可以加排序) groupsArray.sort((a, b) => a.Rank - b.Rank);
为什么这个方案高效?
- 单次遍历数据:只需要把所有数据过一遍,每个数据对应更新一次统计值,没有重复遍历
- 映射对象缓存:用
rankStatsMap快速定位每个Rank的统计对象,避免了嵌套循环里的重复判断 - 最后转数组:只需要遍历一次映射对象的键,就能生成目标数组,额外开销极小
这个方案不管你的数据量是几十条还是几万条,性能都能保持稳定,完全解决了你之前的性能问题。
内容的提问来源于stack exchange,提问作者Ashish Sharma
相关产品推荐
相关产品推荐

