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

JavaScript:如何实现可变长度分数数组的多维度升序排序?

如何按可变长度的分数数组依次升序排序(缺失元素视为无穷大)

首先来看你的需求:你需要对一个包含标签和可变长度分数数组的列表进行排序,排序规则是按分数数组的元素依次升序比较,缺失的元素视为无穷大(排在末尾)。下面分两种方案来实现——原生JavaScript和Lodash,同时解答你的疑问:


问题回顾

先明确你的输入和预期输出:

输入数组

[
  ["Label6", [1]],
  ["Label5", [1,5]],
  ["Label2", [0,1,3,5]],
  ["Label1", [0,1,2]],
  ["Label3", [0,1,4]],
  ["Label4", [1,4]]
]

预期排序结果

[
  ["Label1", [0,1,2]],
  ["Label2", [0,1,3,5]],
  ["Label3", [0,1,4]],
  ["Label4", [1,4]],
  ["Label5", [1,5]],
  ["Label6", [1]]
]

解决方案

一、原生JavaScript实现(无需依赖)

原生ES6并没有直接提供类似Ruby list.sort_by(&:last)的sortBy方法,但我们可以利用数组的sort()方法,传入自定义的比较函数来实现需求,逻辑非常直观:

const options = [
  ["Label6", [1]],
  ["Label5", [1,5]],
  ["Label2", [0,1,3,5]],
  ["Label1", [0,1,2]],
  ["Label3", [0,1,4]],
  ["Label4", [1,4]]
];

// 先复制原数组避免修改原数据,然后排序
const sortedOptions = [...options].sort((a, b) => {
  const scoresA = a[1];
  const scoresB = b[1];
  // 取两个分数数组的最大长度,确保遍历到所有需要比较的位置
  const maxLength = Math.max(scoresA.length, scoresB.length);

  for (let i = 0; i < maxLength; i++) {
    // 数组越界时用Infinity替代,保证缺失元素排在末尾
    const valA = scoresA[i] ?? Infinity;
    const valB = scoresB[i] ?? Infinity;

    // 找到第一个不相等的元素,直接返回差值实现升序
    if (valA !== valB) {
      return valA - valB;
    }
  }

  // 兜底逻辑:如果所有对应元素都相等,长度短的排在后面(其实上面的Infinity已经处理了,这里是冗余但安全的写法)
  return scoresA.length - scoresB.length;
});

console.log(sortedOptions);

核心逻辑说明:

  • 遍历两个分数数组的每个索引位置,依次比较对应元素
  • 当某个索引超出数组长度时,用Infinity替代(升序排序中Infinity会被排在最后)
  • 一旦找到第一个不相等的元素,立即返回比较结果,停止后续遍历
  • 用扩展运算符[...options]复制原数组,避免排序时修改原数据

二、使用Lodash实现

如果你已经在项目中使用Lodash,可以利用它的sortBy方法,但需要做一点小处理——因为默认情况下sortBy会把undefined(数组越界时的值)排在前面,不符合我们的需求,所以要把缺失的元素转换成Infinity:

const _ = require('lodash');

const options = [
  ["Label6", [1]],
  ["Label5", [1,5]],
  ["Label2", [0,1,3,5]],
  ["Label1", [0,1,2]],
  ["Label3", [0,1,4]],
  ["Label4", [1,4]]
];

// 先获取所有分数数组的最大长度,确定需要比较的维度
const maxScoreLength = _.maxBy(options, item => item[1].length)[1].length;

// 为每个维度生成一个迭代函数,把缺失元素转为Infinity
const sortKeys = Array.from({ length: maxScoreLength }, (_, index) => {
  return item => item[1][index] ?? Infinity;
});

// 用Lodash的sortBy依次按每个维度排序
const sortedOptions = _.sortBy(options, ...sortKeys);

console.log(sortedOptions);

逻辑说明:

  • 先找到最长的分数数组长度,确定需要比较多少个维度
  • 为每个维度生成一个迭代函数,返回对应位置的元素或Infinity
  • 把这些迭代函数传入sortBy,它会按顺序依次进行排序,完美匹配你的需求

疑问解答

  • 原生ES6没有直接的sortBy方法可以完全替代Ruby的list.sort_by(&:last),但通过Array.sort()自定义比较函数可以轻松实现需求,而且不需要额外依赖。
  • Lodash/Underscore的sortBy可以实现类似效果,但需要针对缺失元素做特殊处理,把undefined转为Infinity,否则排序结果会不符合预期。

内容的提问来源于stack exchange,提问作者Cyril Duchon-Doris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:27:53