如何根据另一对象数组的顺序对对象数组进行排序?
解决数组按目标顺序排序的问题
嘿,这个需求挺常见的,我来分享个高效的实现方式~
核心思路
我们可以先基于arrayInProperOrder创建一个顺序映射表,把每个对象的field值和它在目标数组里的索引对应起来。然后用这个映射表作为排序依据,对outOfOrderArray进行排序就行。
代码实现
const outOfOrderArray = [{field: 'foo'}, {field: 'bar'}, {field: 'bazz'}, {field: 'bizz'}]; const arrayInProperOrder = [{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}]; // 第一步:创建field到目标索引的映射表 const orderMap = new Map(arrayInProperOrder.map((item, index) => [item.field, index])); // 第二步:基于映射表排序,用扩展运算符复制原数组避免修改原数据 const sortedArray = [...outOfOrderArray].sort((a, b) => { return orderMap.get(a.field) - orderMap.get(b.field); }); console.log(sortedArray); // 输出:[{field: 'bizz'}, {field: 'bazz'}, {field: 'foo'}, {field: 'bar'}]
细节说明
- 使用
Map是因为它的键值对查找效率是O(1),比每次排序都遍历目标数组找索引要高效得多(后者时间复杂度是O(n*m log m),我们的方法是O(n + m log m))。 - 用
[...outOfOrderArray]复制原数组是为了不破坏原数组的结构,如果你的场景允许直接修改原数组,也可以去掉扩展运算符直接调用.sort()。
处理边界情况
如果outOfOrderArray里存在arrayInProperOrder没有的元素,我们可以把这些元素默认排到数组末尾(或者开头),只需要修改排序逻辑:
const sortedArray = [...outOfOrderArray].sort((a, b) => { const aIndex = orderMap.get(a.field) ?? Infinity; const bIndex = orderMap.get(b.field) ?? Infinity; return aIndex - bIndex; });
这样所有不在目标顺序里的元素都会被放到最后。
内容的提问来源于stack exchange,提问作者Bobby Tables
相关产品推荐
相关产品推荐

