如何对按订单号排序的订单列表实现同客户订单分组聚合
订单按客户聚合展示的实现思路
核心逻辑
要实现同客户订单聚合、同时保留原有客户组相对顺序的效果,本质是对列表做双维度优先级排序:
- 第一排序维度:每个客户在原始列表中的首次出现位置,保证客户组之间的顺序和原列表(按订单号排序)的先后一致,不会打乱原有客户出现的先后顺序
- 第二排序维度:单客户组内的订单号大小,保证同一客户下的订单按原本的Order No顺序排列
这种排序方式的输出结果和给出的示例效果完全匹配。
分场景实现方案
前端纯JS处理(适合已加载全量订单数据的页面)
- 遍历原始订单列表,记录每个客户的首次出现索引值:
// 存储每个客户的首次出现位置 const customerFirstPos = {}; let posMark = 0; originalOrderList.forEach(order => { if(!customerFirstPos[order.customer]) { customerFirstPos[order.customer] = posMark++; } }) - 基于记录的索引值,对列表做自定义排序:
const sortedList = [...originalOrderList].sort((a, b) => { // 优先按客户组的先后顺序排 const groupSortDiff = customerFirstPos[a.customer] - customerFirstPos[b.customer]; if(groupSortDiff !== 0) return groupSortDiff; // 同客户组内按订单号升序排 return a.orderNo - b.orderNo; }) - 用排序后的列表重新渲染表格即可。
后端SQL处理(适合从数据库直接取数的场景)
如果使用支持窗口函数的数据库(如MySQL 8.0+、PostgreSQL等),可以直接在查询阶段完成排序,不需要额外写前端处理逻辑:
SELECT customer, order_no FROM orders ORDER BY -- 按每个客户的最小订单号排序,等价于记录客户的首次出现位置(因为原列表按订单号升序) MIN(order_no) OVER (PARTITION BY customer) ASC, order_no ASC
成熟表格组件适配
如果使用Ant Design、Element UI这类前端表格组件,不需要手写排序逻辑:
- 在组件的自定义排序配置中,把「客户首次出现位置的映射值」设为第一排序优先级,「Order No」设为第二排序优先级即可。
- 注意不要直接把Customer字段设为第一排序键,否则会按客户名称的字典序重排客户组,打乱原列表的客户出现顺序,和示例效果不匹配。
内容的提问来源于stack exchange,提问作者Mateusz Makowczyński
相关产品推荐
相关产品推荐

