按自定义类型顺序及名称字母序排序对象数组失败排查
自定义排序中二级字母序排序失效的原因及解决方法
问题场景
要对对象数组先按自定义type顺序排序,再按name字母序排序,示例数据如下:
const preData = [ { type: "veggie", name: "Tomato salad" }, { type: "veggie", name: "Cole slaw" }, { type: "veggie", name: "Nothing" }, { type: "meat", name: "Spare-ribs" }, { type: "meat", name: "Steak" }, { type: "meat", name: "Pulled pork" }, { type: "potato", name: "Pommes frites" }, { type: "potato", name: "Curly fries" }, { type: "potato", name: "King size frites" } ];
使用的排序代码:
const sortOrder = { meat: 1, potato: 2, veggie: 3 }; const postData = preData.sort((a, b) => (sortOrder[a.type] || Number.MAX_VALUE) - (sortOrder[b.type] || Number.MAX_VALUE) || (a.name.toUpperCase() > b.name.toUpperCase()));
实际仅完成了type排序,同type内的name字母序排序未生效。
失效原因
JavaScript数组的sort()方法要求回调函数返回数字值(正数、负数或0):
- 返回正数:
a排在b后面 - 返回负数:
a排在b前面 - 返回0:
a和b位置不变
你的二级排序部分a.name.toUpperCase() > b.name.toUpperCase()返回的是布尔值:
- 当
a.name比b.name字母序靠后时,返回true(被转为数字1),这部分逻辑正确 - 当
a.name比b.name字母序靠前时,返回false(被转为数字0),这会让sort()认为两者位置不需要交换,导致排序失效 - 当两者相等时返回0,这部分没问题
解决方法
把二级排序的逻辑改成返回符合要求的数字,推荐使用String.localeCompare()方法,它会直接返回排序所需的正数、负数或0,同时支持更通用的字母排序规则:
const sortOrder = { meat: 1, potato: 2, veggie: 3 }; const postData = preData.sort((a, b) => { // 先按type自定义顺序排序 const typeDiff = (sortOrder[a.type] || Number.MAX_VALUE) - (sortOrder[b.type] || Number.MAX_VALUE); if (typeDiff !== 0) { return typeDiff; } // 同type时按name字母序排序,转大写避免大小写影响 return a.name.toUpperCase().localeCompare(b.name.toUpperCase()); });
也可以手动判断返回数字:
const sortOrder = { meat: 1, potato: 2, veggie: 3 }; const postData = preData.sort((a, b) => { const typeDiff = (sortOrder[a.type] || Number.MAX_VALUE) - (sortOrder[b.type] || Number.MAX_VALUE); if (typeDiff !== 0) { return typeDiff; } const nameA = a.name.toUpperCase(); const nameB = b.name.toUpperCase(); if (nameA > nameB) return 1; if (nameA < nameB) return -1; return 0; });
内容的提问来源于stack exchange,提问作者GePu
相关产品推荐
相关产品推荐

