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

如何实现通用多键稳定排序函数?对对象数组按指定键序列排序

如何实现一个支持多键排序的通用对象数组排序函数?

我需要实现一个通用排序函数,能够接收任意对象数组和一个键列表,按照键的顺序对数组进行排序——先按第一个键排序,当第一个键值相同时,再按第二个键排序,以此类推,同时要支持字符串和数字类型的键值。

示例场景

输入数组:

const input = [
  { a: 'aardvark', b: 'bear', c: 'camel', d: 1 },
  { a: 'anemone', b: 'bat', c: 'cobra', d: 6 },
  { a: 'aardvark', b: 'badger', c: 'camel', d: 2 },
  { a: 'alligator', b: 'bat', c: 'chicken', d: 2 },
  { a: 'alligator', b: 'beetle', c: 'cow', d: 1 },
  { a: 'alligator', b: 'bat', c: 'crab', d: 3 },
]

调用函数:

sortFunction(['a', 'b', 'd'], input)

预期输出:

[
  { a: 'aardvark', b: 'badger', c: 'camel', d: 2 },
  { a: 'aardvark', b: 'bear', c: 'camel', d: 1 },
  { a: 'alligator', b: 'bat', c: 'chicken', d: 2 },
  { a: 'alligator', b: 'bat', c: 'crab', d: 3 },
  { a: 'alligator', b: 'beetle', c: 'cow', d: 1 },
  { a: 'anemone', b: 'bat', c: 'cobra', d: 6 },
]

排序规则说明

  • 优先按键a升序排序(示例中aardvark < alligator < anemone)
  • 当a值相同时,按键b升序排序(比如aardvark组里badger < bear)
  • 当a和b值都相同时,按键d升序排序(alligator+bat组里d=2排在d=3前面)

现在需要把这个逻辑做成通用函数,适配任意对象数组和键列表,同时兼容字符串、数字类型的键值比较。


实现方案

核心思路

利用数组原生的sort方法,遍历传入的键列表依次比较对象的对应键值:

  • 若当前键的两个值不相等,直接返回比较结果,终止后续键的比较
  • 若当前键值相等,则继续用下一个键进行比较
  • 所有键都比较完仍相等时,返回0以保持原数组的相对顺序

通用函数实现

function sortFunction(keys, arr) {
  // 复制原数组,避免排序操作修改原数据
  return [...arr].sort((objA, objB) => {
    for (const key of keys) {
      const valA = objA[key];
      const valB = objB[key];
      
      // 数字类型直接相减实现升序
      if (typeof valA === 'number' && typeof valB === 'number') {
        const diff = valA - valB;
        if (diff !== 0) return diff;
      } 
      // 字符串用localeCompare实现自然排序
      else if (typeof valA === 'string' && typeof valB === 'string') {
        const compareResult = valA.localeCompare(valB);
        if (compareResult !== 0) return compareResult;
      } 
      // 混合类型转字符串后统一比较
      else {
        const strA = String(valA);
        const strB = String(valB);
        const compareResult = strA.localeCompare(strB);
        if (compareResult !== 0) return compareResult;
      }
    }
    // 所有键值都相同,保持原顺序
    return 0;
  });
}

代码细节解释

  1. 无副作用排序:通过[...arr]浅拷贝原数组,确保排序操作不会影响原始数据
  2. 多键优先级处理:遍历键列表时,只要某一键的比较结果非0,就直接作为排序依据,保证前序键的排序优先级更高
  3. 类型兼容:
    • 数字类型用减法实现高效的升序比较
    • 字符串用localeCompare支持自然语言排序(如大小写不敏感、特殊字符排序)
    • 混合类型自动转字符串处理,避免类型错误
  4. 稳定排序:所有键值相同时返回0,配合现代浏览器对ES2019+稳定sort的支持,能保持原数组中相同项的相对位置

扩展:支持指定单个键的排序方向

如果需要为每个键单独设置升序/降序,可以将键列表改为配置对象数组,示例如下:

function sortFunction(sortConfig, arr) {
  return [...arr].sort((objA, objB) => {
    for (const { key, order = 'asc' } of sortConfig) {
      const valA = objA[key];
      const valB = objB[key];
      let compareResult;
      
      if (typeof valA === 'number' && typeof valB === 'number') {
        compareResult = valA - valB;
      } else {
        const strA = String(valA);
        const strB = String(valB);
        compareResult = strA.localeCompare(strB);
      }
      
      // 降序时反转比较结果
      if (order === 'desc') compareResult *= -1;
      if (compareResult !== 0) return compareResult;
    }
    return 0;
  });
}

// 使用示例:指定a键降序,b、d键升序
sortFunction(
  [{key: 'a', order: 'desc'}, {key: 'b', order: 'asc'}, {key: 'd', order: 'asc'}],
  input
);

内容的提问来源于stack exchange,提问作者turtle

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 19:10:29