如何对含版本号与字母的JavaScript数组按规则排序?
问题描述
我有如下JavaScript数组:
input = [ "1.1", "1.c", "1.b", "1", "D", "b", "4", "2.1.2", "5.1", "3", "2.a.1" ]
希望将其排序为如下结果:
sorted = [ "1", "1.1", "1.b", "1.c", "b", "2.a.1", "2.1.2", "3", "4", "D", "5.1" ]
排序规则为:a或A等价于1,b或B等价于2,以此类推。数组仅包含数字与字母,无其他符号。
我尝试用localeCompare排序,但没得到预期结果:
input = ["1", "1.1", "1.b", "1.c", "b", "2.a.1", "2.1.2", "3", "4", "D", "5.1"] console.log(input.sort((a, b) => a.localeCompare(b)));
解决思路
默认的localeCompare按字符Unicode编码排序,比如数字2的编码比字母a小,会导致2.1.2排在2.a.1前面,不符合需求。要实现自定义规则,需把每个元素转换成可按数字顺序比较的结构:
- 将元素按
.分割为子段(比如"2.a.1"分割为["2", "a", "1"]); - 子段转数字:字母转对应序号(a→1,b→2…,大小写不敏感),数字字符串直接转数字;
- 对比两个元素的转换结果数组,逐段比较数字大小,短数组排在前面(比如
"1"的转换数组[1]排在"1.1"的[1,1]前面)。
代码实现
const input = [ "1.1", "1.c", "1.b", "1", "D", "b", "4", "2.1.2", "5.1", "3", "2.a.1" ]; // 将单个子段转换为数字:字母转序号,数字转Number const segmentToNum = (seg) => { if (/^[a-zA-Z]$/.test(seg)) { return seg.toLowerCase().charCodeAt(0) - 96; // a的charCode是97,97-96=1 } return Number(seg); }; // 把整个元素转换为可比较的数字数组 const convertToCompareArray = (str) => { return str.split('.').map(segmentToNum); }; // 自定义排序比较函数 input.sort((a, b) => { const arrA = convertToCompareArray(a); const arrB = convertToCompareArray(b); // 逐段对比数字 for (let i = 0; i < Math.min(arrA.length, arrB.length); i++) { if (arrA[i] !== arrB[i]) { return arrA[i] - arrB[i]; } } // 前面段都相同,短的元素排前面 return arrA.length - arrB.length; }); console.log(input); // 输出结果:["1","1.1","1.b","1.c","b","2.a.1","2.1.2","3","4","D","5.1"]
代码解释
segmentToNum:判断子段类型,字母转对应序号,数字字符串转数字;convertToCompareArray:分割元素后,将每个子段转换为数字,得到用于比较的数组;- 排序函数:先转换两个元素为数字数组,逐段对比找到第一个不同值返回差值;若前序段都相同,长度短的元素优先。
内容的提问来源于stack exchange,提问作者Imran Al Rashid
相关产品推荐
相关产品推荐

