如何实现通用多键稳定排序函数?对对象数组按指定键序列排序
如何实现一个支持多键排序的通用对象数组排序函数?
我需要实现一个通用排序函数,能够接收任意对象数组和一个键列表,按照键的顺序对数组进行排序——先按第一个键排序,当第一个键值相同时,再按第二个键排序,以此类推,同时要支持字符串和数字类型的键值。
示例场景
输入数组:
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; }); }
代码细节解释
- 无副作用排序:通过
[...arr]浅拷贝原数组,确保排序操作不会影响原始数据 - 多键优先级处理:遍历键列表时,只要某一键的比较结果非0,就直接作为排序依据,保证前序键的排序优先级更高
- 类型兼容:
- 数字类型用减法实现高效的升序比较
- 字符串用
localeCompare支持自然语言排序(如大小写不敏感、特殊字符排序) - 混合类型自动转字符串处理,避免类型错误
- 稳定排序:所有键值相同时返回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
相关产品推荐
相关产品推荐

