JavaScript:对象数组特殊排序——同ID记录需上浮至同组最小num后
高效实现特殊排序需求
这个需求的核心是既要整体按num升序,又要将同一id的所有记录聚合在该id最小num值的位置后方,而且要适配15000+条数据的高效处理。你之前的基础排序逻辑只处理了num的升序,缺少同id聚合的关键逻辑,我们可以通过「预处理+自定义排序」的方案来解决,保证效率。
方案思路
- 预处理阶段:先遍历一次数组,用
Map记录每个id对应的最小num值。这一步是O(n)时间复杂度,非常高效,避免了排序时重复计算的开销。 - 排序阶段:利用预处理好的
Map,自定义排序规则:- 优先按「当前
id的最小num值」升序排列,这样同一id的记录会被自动归为一组,排在该id最小num的位置附近; - 若两个记录属于同一
id,则按自身num升序排列(保证同id内的顺序); - 若不同
id但最小num相同,则按自身num升序(符合整体排序要求)。
- 优先按「当前
完整代码实现
// 原始数据示例 const origData = [{"id":"ABC","num":111}, {"id":"DEF","num":130}, {"id":"XYZ","num":115}, {"id":"QRS","num":98}, {"id":"DEF","num":119}, {"id":"ABC","num":137}, {"id":"LMN","num":122}, {"id":"ABC","num":108}]; // 第一步:预处理,记录每个id的最小num值 const idMinNumMap = new Map(); origData.forEach(item => { const currentMin = idMinNumMap.get(item.id); // 如果当前id还没记录,或者当前item的num更小,更新最小num if (currentMin === undefined || item.num < currentMin) { idMinNumMap.set(item.id, item.num); } }); // 第二步:执行排序(用扩展运算符复制原数组,避免修改原数据) const sortedData = [...origData].sort((a, b) => { const minNumA = idMinNumMap.get(a.id); const minNumB = idMinNumMap.get(b.id); // 优先按id对应的最小num升序,确保同id的记录聚在一起 if (minNumA !== minNumB) { return minNumA - minNumB; } // 同id的记录,按自身num升序排列 if (a.id === b.id) { return a.num - b.num; } // 不同id但最小num相同,按自身num升序 return a.num - b.num; }); console.log(sortedData); // 输出结果与你期望的完全一致
为什么这个方案高效?
- 预处理只需要一次遍历,时间复杂度O(n),对于15000条数据来说几乎是瞬间完成;
- 排序阶段的比较函数每次只做O(1)的Map查找,而JS引擎的
sort方法是经过高度优化的(一般是Timsort算法),整体时间复杂度为O(n log n),完全能轻松处理15000+条数据; - 避免了在排序比较函数中重复计算每个
id的最小num(如果这么做,时间复杂度会飙升到O(n² log n),数据量大的时候会非常慢)。
内容的提问来源于stack exchange,提问作者JDR
相关产品推荐
相关产品推荐

