如何实现带特殊条件的JavaScript对象数组自定义排序
基于point属性的特殊规则数组排序实现
核心排序规则
- 先将原数组元素按
English、Math、History三个学科分组,分组内保留元素在原数组中的先后顺序 - 默认排列逻辑:按轮次从每个分组取2个元素拼接结果集,第一轮取English前2个、Math前2个、History前2个,第二轮取各组第3、4个元素,后续轮次以此类推,默认排列结构如下:
ENGLISH[0] ENGLISH[1] MATH[0] MATH[1] HISTORY[0] HISTORY[1] ENGLISH[2] MATH[2] ...
- 特殊调整规则:计算两组比值,当满足
ENGLISH[0].point / ENGLISH[1].point > MATH[0].point / MATH[1].point时,仅交换第一轮排列中English、Math两个分组前两位元素的位置,其余轮次、其余分组的排列顺序保持不变,调整后第一轮结构如下:
MATH[0] MATH[1] ENGLISH[0] ENGLISH[1] HISTORY[0] HISTORY[1] ...
待排序示例输入
const arr = [ { name: "John", age: 32, group: "Math", point: 70 }, { name: "David", age: 23, group: "Math", point: 20 }, { name: "Justin", age: 28, group: "Math", point: 20 }, { name: "Neymar", age: 30, group: "Math", point: 50 }, { name: "Arnauld", age: 35, group: "History", point: 40 }, { name: "Ivan", age: 18, group: "History", point: 50 }, { name: "Nekko", age: 13, group: "History", point: 80 }, { name: "Lena", age: 25, group: "English", point: 90 }, { name: "Test", age: 45, group: "English", point: 30 }, { name: "Ann", age: 19, group: "English", point: 38 } ]
期望输出结果
const result = [ { name: "Lena", age: 25, group: "English", point: 90 }, { name: "Test", age: 45, group: "English", point: 30 }, { name: "John", age: 32, group: "Math", point: 70 }, { name: "David", age: 23, group: "Math", point: 20 }, { name: "Arnauld", age: 35, group: "History", point: 40 }, { name: "Ivan", age: 18, group: "History", point: 50 }, { name: "Ann", age: 19, group: "English", point: 38 }, { name: "Justin", age: 28, group: "Math", point: 20 }, { name: "Neymar", age: 30, group: "Math", point: 50 }, { name: "Nekko", age: 13, group: "History", point: 80 } ]
实现代码
function specialSort(arr) { // 按学科分组,保留原数组内元素顺序 const groups = { English: arr.filter(item => item.group === 'English'), Math: arr.filter(item => item.group === 'Math'), History: arr.filter(item => item.group === 'History') } // 判定第一轮是否需要交换English和Math的位置 const engRatio = groups.English[0].point / groups.English[1].point const mathRatio = groups.Math[0].point / groups.Math[1].point const needSwap = engRatio > mathRatio const firstRoundOrder = needSwap ? ['Math', 'English', 'History'] : ['English', 'Math', 'History'] const result = [] let round = 0 // 逐轮取元素,每轮每个分组取2个 while (true) { const batch = [] // 仅第一轮使用调整后的顺序,后续轮次使用默认顺序 const currentOrder = round === 0 ? firstRoundOrder : ['English', 'Math', 'History'] for (const groupName of currentOrder) { const group = groups[groupName] const firstIdx = round * 2 const secondIdx = round * 2 + 1 if (group[firstIdx]) batch.push(group[firstIdx]) if (group[secondIdx]) batch.push(group[secondIdx]) } // 本轮无元素可取,说明所有元素处理完成 if (batch.length === 0) break result.push(...batch) round++ } return result } // 测试示例 const arr = [ { name: "John", age: 32, group: "Math", point: 70 }, { name: "David", age: 23, group: "Math", point: 20 }, { name: "Justin", age: 28, group: "Math", point: 20 }, { name: "Neymar", age: 30, group: "Math", point: 50 }, { name: "Arnauld", age: 35, group: "History", point: 40 }, { name: "Ivan", age: 18, group: "History", point: 50 }, { name: "Nekko", age: 13, group: "History", point: 80 }, { name: "Lena", age: 25, group: "English", point: 90 }, { name: "Test", age: 45, group: "English", point: 30 }, { name: "Ann", age: 19, group: "English", point: 38 } ] console.log(specialSort(arr)) // 输出与期望结果完全一致
逻辑说明:示例中English前两位比值为
90/30=3,Math前两位比值为70/20=3.5,不满足交换条件,因此第一轮按默认顺序排列,最终输出和预期结果匹配。
内容的提问来源于stack exchange,提问作者davidann
相关产品推荐
相关产品推荐

