使用reduce处理数组 实现指定Description项不聚合单独输出
数组差异化聚合处理问题
原有实现
当前通过reduce实现数组字段提取与聚合,代码如下:
data_proces = Object.values(selectedData.reduce((r, { Code, Description, Price}) => { r[Description] ??= { Code, Description, Units: 0, Price: 0 , Total: 0}; r[Description].Code= Code; r[Description].Units++; r[Description].Price = Price ; r[Description].Total += Price ; return r; }, {}));
现有输出
上述代码对所有条目按Description做全量聚合,输出结果如下:
[ { "Code": 0, "Description": "No Factured Act", "Units": 2, "Price": 0, "Total": 0 }, { "Code": 1, "Description": "Autopsy", "Units": 1, "Price": 44, "Total": 44 }, { "Code": 2, "Description": "Simple Biopsy", "Units": 3, "Price": 29, "Total": 87 }, { "Code": 1, "Description": "Citology", "Units": 4, "Price": 15, "Total": 60 }, { "Code": " -", "Description": "Free Act", "Units": 2, "Price": 56789, "Total": 91356 } ]
需求规则
需要调整聚合逻辑,两类条目执行不同处理规则:
Description为No Factured Act、Free Act的条目:不做聚合,每条原始记录单独生成独立对象,单条对象Units固定为1,Total等于当前条目的Price- 其余
Description的条目:保持原有聚合逻辑,按Description分组,累加Units、Total字段,Code、Price取分组内最新遍历到的值
期望输出结构参考(修正原示例的JSON语法笔误):
[ { "Code": 0, "Description": "No Factured Act", "Units": 1, "Price": 0, "Total": 0 }, { "Code": 0, "Description": "No Factured Act", "Units": 1, "Price": 0, "Total": 0 }, { "Code": 1, "Description": "Autopsy", "Units": 1, "Price": 44, "Total": 44 }, { "Code": 2, "Description": "Simple Biopsy", "Units": 3, "Price": 29, "Total": 87 }, { "Code": 1, "Description": "Citology", "Units": 4, "Price": 15, "Total": 60 }, { "Code": " -", "Description": "Free Act", "Units": 1, "Price": 34567, "Total": 34567 }, { "Code": " -", "Description": "Free Act", "Units": 1, "Price": 56789, "Total": 56789 } ]
实现代码
核心调整点是把reduce的累加器从空对象改为空数组,遍历过程中加分支判断区分两类条目即可,完整实现如下:
// 定义不需要聚合的Description集合,判断时间复杂度O(1) const skipAggregateDesc = new Set(["No Factured Act", "Free Act"]); const data_proces = selectedData.reduce((result, { Code, Description, Price }) => { // 非聚合条目直接生成独立对象推入结果 if (skipAggregateDesc.has(Description)) { result.push({ Code, Description, Units: 1, Price, Total: Price }); return result; } // 聚合条目先查找是否已存在同Description的分组 const existingGroup = result.find(item => item.Description === Description); if (existingGroup) { // 已存在分组则更新字段、做累加 existingGroup.Code = Code; existingGroup.Units++; existingGroup.Price = Price; existingGroup.Total += Price; } else { // 不存在分组则新建初始条目 result.push({ Code, Description, Units: 1, Price, Total: Price }); } return result; }, []);
性能提示:如果待处理数据量超过1000条,可以额外维护一个Description对应数组索引的映射对象,替代find遍历查找,将分组查找的复杂度从O(n)降到O(1);中小数据量场景下上述写法可读性更高,没有性能问题。
内容的提问来源于stack exchange,提问作者Javier
相关产品推荐
相关产品推荐

