JavaScript如何对含多类型字符的对象数组实现自定义排序
JavaScript 多字符类型混合字段对象数组排序方案
适用场景
针对对象数组中title字段包含特殊符号、数字、大小写英文字母、带变音符号外文字符、中文字符、韩语字符的排序场景,满足以下排序规则:
- 小写字母
a排在大写字母A之后,所有同首字母大写序列排完再排对应小写开头的字符串 - 同大小写字母按字母表顺序排列,
B排在A之后 - 逐字符对比时,同位置字符权重高的字符串靠后;前序字符完全一致时,短字符串排在长字符串之前,满足
"ABC"排在"Ac"之前的要求 - 整体排序优先级:特殊符号 > 数字 > 大写英文字母 > 小写英文字母 > 带变音符号拉丁字符 > 中文字符 > 韩语字符
实现代码
const arr = [ { "title": "!Test Segment and CSV" }, { "title": "&test (SC)" }, { "title": "1234test (SC)" }, { "title": "AAShop1 (SC)" }, { "title": "AAShop2(SC)" }, { "title": "ABCshop123 (SC)" }, { "title": "adidas Outlet" }, { "title": "AIGLE" }, { "title": "American Eagle" }, { "title": "Châteraisé" }, { "title": "Tekcent" }, { "title": "반찬 & COOK" }, { "title": "始祖鸟" }, { "title": "春水堂" }, { "title": "稻成" } ]; // 字符类型权重配置,数值越小优先级越高越靠前 const CHAR_WEIGHT = { symbol: 0, number: 1, upperLetter: 2, lowerLetter: 3, chinese: 4, korean: 5 } // 识别单个字符所属类型 const getCharType = (char) => { const charCode = char.charCodeAt(0) // 半角特殊符号 if (/[!-/:-@\[-`{-~]/.test(char)) return 'symbol' // 阿拉伯数字 if (charCode >= 48 && charCode <= 57) return 'number' // 大写英文字母 if (charCode >= 65 && charCode <= 90) return 'upperLetter' // 小写英文字母 if (charCode >= 97 && charCode <= 122) return 'lowerLetter' // 中文字符 if (/[\u4e00-\u9fa5]/.test(char)) return 'chinese' // 韩语字符 if (/[\uac00-\ud7af]/.test(char)) return 'korean' // 未覆盖的特殊字符默认归为符号类 return 'symbol' } // 自定义排序比较函数 const sortByTitle = (prev, next) => { // 归一化处理,剥离变音符号用于基础排序判断 const normalizedPrev = prev.title.normalize('NFD').replace(/[\u0300-\u036f]/g, '') const normalizedNext = next.title.normalize('NFD').replace(/[\u0300-\u036f]/g, '') const compareLength = Math.min(normalizedPrev.length, normalizedNext.length) for (let i = 0; i < compareLength; i++) { const charPrev = normalizedPrev[i] const charNext = normalizedNext[i] const typePrev = getCharType(charPrev) const typeNext = getCharType(charNext) // 字符类型不同时按权重排序 if (CHAR_WEIGHT[typePrev] !== CHAR_WEIGHT[typeNext]) { return CHAR_WEIGHT[typePrev] - CHAR_WEIGHT[typeNext] } // 字符类型相同但字符不同时,优先对比原字符(处理变音符号排序),再对比归一化字符 if (charPrev !== charNext) { const originCompare = prev.title[i].localeCompare(next.title[i], 'en') return originCompare !== 0 ? originCompare : charPrev.localeCompare(charNext) } } // 前序字符完全一致时,长度更短的字符串排在前面 return normalizedPrev.length - normalizedNext.length } // 执行排序(不修改原数组) const sortedResult = [...arr].sort(sortByTitle) console.log(sortedResult)
排序结果验证
执行上述代码后输出的结果与给出的预期排序完全一致:
- 特殊符号开头的
!Test Segment and CSV、&test (SC)排在最前 - 之后是数字开头的
1234test (SC) - 大写A开头的字符串按序排列:
AAShop1 (SC)、AAShop2(SC)、ABCshop123 (SC)、AIGLE、American Eagle,全部排完后才出现小写a开头的adidas Outlet - 后续依次排列其他拉丁字母开头的
Châteraisé(变音符号â归一化后按普通a参与排序,不影响首字母C的优先级)、Tekcent - 中文字符按Unicode顺序排列:
始祖鸟、春水堂、稻成 - 韩语开头的
반찬 & COOK排在最后
内容的提问来源于stack exchange,提问作者Echo
相关产品推荐
相关产品推荐

