TypeScript如何按字母数字字符串属性值正确排序对象数组
TypeScript 实现按targetRange属性正确排序对象数组
问题背景
待排序对象数组结构如下,需要按照targetRange字段(类Excel单元格地址格式,结构为列字母+行数字)排序,预期顺序为A1 → A2 → B2:
const objs = [ { "title": "Picture3.jpg", "targetRange": "B2", "type": "Bitmap" }, { "title": "Picture2.jpg", "targetRange": "A2", "type": "Bitmap" }, { "title": "Picture1.jpg", "targetRange": "A1", "type": "Bitmap" } ]
此前尝试的两种排序方案均未得到正确结果:
// 方案1 this.objs.sort((a, b) => a.targetRange!.localeCompare(b.targetRange!)); // 方案2 this.objs.sort((a,b) => (a.targetRange! < b.targetRange!) ? 1 : ((b.targetRange! > a.targetRange!) ? -1 : 0))
失效原因
- 方案1直接使用字符串默认排序规则,逐字符比较内容:当行号为多位数时(例如A10、A2),会因为字符
1小于2,错误将A10排在A2之前,不符合单元格地址的排序逻辑。 - 方案2写反了升降序判断逻辑:当
a.targetRange小于b.targetRange时返回1,等价于强制按降序排列,自然无法得到升序结果,同时也存在和方案1一致的多位数行号排序错误问题。
正确实现
排序核心思路是将单元格地址拆分为列字母段和行号数字段,先按列字母的字典序比较,列相同时将行号转为数字后比较数值大小,完全匹配Excel单元格的排序规则,同时兼容大小写、多位数行号场景:
/** * 拆分Excel单元格地址为列标识、行号 */ const splitCellRange = (range: string) => { const matchRes = range.match(/^([A-Za-z]+)(\d+)$/); // 格式异常时兜底返回 if (!matchRes) return { col: range.toUpperCase(), row: 0 }; return { col: matchRes[1].toUpperCase(), // 列字母统一转大写,消除大小写差异影响 row: parseInt(matchRes[2], 10) // 行号转整数,避免字符串比较的多位数错误 }; }; // 执行排序 this.objs.sort((a, b) => { const rangeA = splitCellRange(a.targetRange!); const rangeB = splitCellRange(b.targetRange!); // 先比较列 if (rangeA.col !== rangeB.col) { return rangeA.col.localeCompare(rangeB.col); } // 列一致时比较行号 return rangeA.row - rangeB.row; });
执行后返回的排序结果完全符合预期:
[ { "title": "Picture1.jpg", "targetRange": "A1", "type": "Bitmap" }, { "title": "Picture2.jpg", "targetRange": "A2", "type": "Bitmap" }, { "title": "Picture3.jpg", "targetRange": "B2", "type": "Bitmap" } ]
内容的提问来源于stack exchange,提问作者Chris
相关产品推荐
相关产品推荐

