JavaScript如何对字母数字混合数组先按文本后按数值排序
问题描述
现有如下字母数字混合数组:
["1","0K","11",1,"KE","PQ",5,"5"]
需要实现先按文本类型排序、后按内容规则排序的效果:纯字母开头的内容排在最前,其次是字母数字混合内容,最后是纯数字内容,同类型内再按自然顺序排序,最终得到如下结果:
["KE","PQ","0K","1",1,5,"5","11"]
当前使用localeCompare实现的排序效果不符合预期,现有代码如下:
function desc(a,b){ //below is the code that needs improvement return b.toString().localeCompare(a, undefined, { numeric: true, sensitivity: "base", }); } function sort(order) { return order === "desc" ? (a, b) => desc(a, b) : (a, b) => -desc(a, b); } function stableSort(array, cmp){ const stabilizedThis = array.map((el, index) => [el, index]); stabilizedThis.sort((a, b) => { const order = cmp(a[0], b[0]); if (order !== 0) return order; return (a[1]) - (b[1]); }); return stabilizedThis.map((el) => el[0]); } var arr = ["1","0K","11",1,"KE","PQ",5,"5"]; console.log(stableSort(arr, sort("asc")))
解决方案
原有逻辑没有区分内容的类型优先级,我们可以先给每个元素打分类标签,排序时先比较类型优先级,同优先级再用localeCompare做内容排序即可,只需要修改desc函数的逻辑:
function desc(a,b){ // 统一转成字符串处理 const strA = a.toString(); const strB = b.toString(); // 分类分级,返回值越小优先级越高 const getTypeRank = (str) => { if(/^[A-Za-z]+$/.test(str)) return 1; // 纯字母类 if(/\D/.test(str)) return 2; // 含非数字字符的混合类 return 3; // 纯数字类 } const rankA = getTypeRank(strA); const rankB = getTypeRank(strB); // 优先按类型排序 if(rankA !== rankB) { return rankB - rankA; } // 同类型下按自然顺序排序 return strB.localeCompare(strA, undefined, { numeric: true, sensitivity: "base", }); }
修改后调用stableSort(arr, sort("asc"))即可输出预期结果。
内容的提问来源于stack exchange,提问作者Nidhi Dadiya
相关产品推荐
相关产品推荐

