JavaScript多条件数组排序代码错误排查
多条件数组排序问题排查
原始数据
待排序数组
const services = [ { id: 100, priority: 'Y', count: 300, payout: '30', id_region: 137 }, { id: 101, priority: 'N', count: 200, payout: '40', id_region: 153 }, { id: 102, priority: 'Y', count: 400, payout: '30', id_region: 137 }, { id: 103, priority: 'Y', count: 500, payout: '50', id_region: 153 }, { id: 104, priority: 'Y', count: 800, payout: '80', id_region: 222 } ];
全局变量
var regionsFound = ['153'];
排序规则
- 优先排列
id_region存在于regionsFound中的元素 - 目标区域内的元素,
priority为'Y'的排在前面 - 目标区域内优先级相同的,按
payout从高到低排序 - 非目标区域的元素排在所有目标区域元素之后
- 非目标区域内按
count从高到低排序
用户现有排序代码
services.sort((a, b) => { if (regionsFound.indexOf(a.id_region.toString()) >= 0 && regionsFound.indexOf(b.id_region.toString()) >= 0){ if (a.priority == 'Y' && b.priority == 'N'){ return -1; } else if (a.priority == 'N' && b.priority == 'Y'){ return 1; } return b.payout - a.payout; } else if (regionsFound.indexOf(a.id_region.toString()) >= 0 && regionsFound.indexOf(b.id_region.toString()) < 0){ return -1; } else { return b.count - a.count; } });
预期排序结果
const services = [ { id: 103, priority: 'Y', count: 500, payout: '50', id_region: 153 }, { id: 101, priority: 'N', count: 200, payout: '40', id_region: 153 }, { id: 104, priority: 'Y', count: 800, payout: '80', id_region: 222 }, { id: 102, priority: 'Y', count: 400, payout: '30', id_region: 137 }, { id: 100, priority: 'Y', count: 300, payout: '30', id_region: 137 } ];
问题排查与修正
错误点分析
- 缺失反向区域判断分支:当
a不在目标区域但b在目标区域时,现有代码直接进入else分支按count比较,导致目标区域元素被错误排在非目标区域元素之后。正确逻辑应让b(目标区域元素)排在a前面,此时需返回1。 - 字符串隐式转换风险:
payout是字符串类型,直接相减依赖JS隐式类型转换,显式转为数字更稳妥,避免潜在异常。
修正后的代码
services.sort((a, b) => { // 提前判断元素是否在目标区域,避免重复计算 const aInRegion = regionsFound.includes(a.id_region.toString()); const bInRegion = regionsFound.includes(b.id_region.toString()); // 区域优先级判断 if (aInRegion && !bInRegion) { return -1; } else if (!aInRegion && bInRegion) { return 1; } // 同一区域内的排序逻辑 else if (aInRegion && bInRegion) { // 优先级判断 if (a.priority === 'Y' && b.priority === 'N') return -1; if (a.priority === 'N' && b.priority === 'Y') return 1; // 按payout降序,显式转数字 return Number(b.payout) - Number(a.payout); } else { // 非目标区域按count降序 return b.count - a.count; } });
运行修正后的代码即可得到预期排序结果。
内容的提问来源于stack exchange,提问作者Klebson Carneiro
相关产品推荐
相关产品推荐

