JavaScript按资源code聚合JSON数组计算可用/总资源数,评估实现效率并探索更优写法
现有实现的效率与逻辑问题评估
- 从效率维度看,当前实现是两次非嵌套的全量遍历,时间复杂度为O(n),对于常规业务量级的资源数据(单次数千到数万条记录)来说完全够用,不存在性能瓶颈。
- 从逻辑正确性看,当前实现存在一个容易忽略的隐患:代码里用
single[item.res_status] = item.avl_res做赋值操作,如果同一个code下出现多条同状态的记录,后面的记录值会直接覆盖前面的数值,没法正确完成数量累加,最终的统计结果会和实际值有偏差。
基于原生数组/对象方法的优化实现
完全可以不用拆成「先存临时对象、再遍历临时对象生成结果」的两段式逻辑,借助Map的O(1)查找特性,用单次遍历完成所有聚合计算,代码更简洁,逻辑也更通顺:
const codeAggMap = new Map(); arr.forEach(item => { // 没有当前code的聚合项就初始化基础结构 if (!codeAggMap.has(item.code)) { codeAggMap.set(item.code, { code: item.code, avl_res: 0, total_res: 0 }); } const aggItem = codeAggMap.get(item.code); // 所有记录的数量都计入总资源 aggItem.total_res += item.avl_res; // 可用状态的记录额外计入可用资源数 if (item.res_status === 'Available') { aggItem.avl_res += item.avl_res; } }); // 直接把Map中存储的聚合项转为最终输出数组 const outputList = Array.from(codeAggMap.values());
这个版本的特点:
- 执行效率和原实现持平,都是O(n)时间复杂度,因为Map的查找、插入操作都是常数时间,比在数组里循环查找同code项的实现效率更高
- 从根源上避免了原实现的覆盖问题,不管同一个code下出现多少条同状态的记录,都是做数值累加,不会出现统计不准的情况
- 不需要在遍历完临时存储后再做二次的状态取值、逻辑判断,每读一条记录就完成所有统计计算,逻辑链路更短
注意:如果业务规则确定同一个code下每个状态最多只会出现1条记录,那原实现的逻辑是可以正常跑出正确结果的,只是可扩展性稍差,一旦出现同code多同状态记录的情况就会出问题。
内容的提问来源于stack exchange,提问作者Konstabel Piksel
相关产品推荐
相关产品推荐

