You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现带特殊条件的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 15:54:06