ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

JS Tips 04:如何正确排序含重音字符的字符串(localeCompare 与 Intl.Collator 实战)

JS Tips 04:如何正确排序含重音字符的字符串(localeCompare 与 Intl.Collator 实战) 教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载本篇是 JS Tips 系列的第 04 篇。它揭示了一个常见的国际化i18n陷阱JavaScript 原生Array.prototype.sort()只按英文字母的码点顺序排序遇到西班牙语、德语等含重音accented字符的非 ASCII 字符串时会产生错序。读完本文你将掌握使用String.prototype.localeCompare()与Intl.Collator两种方案按语言习惯正确排序的方法并能针对不同区域locale定制排序规则避免线上数据出现意外的排列结果。问题原生sort()在非 ASCII 字符串上的错序JavaScript 原生提供了Array.prototype.sort()方法用于排序数组。当不传入比较函数时sort()会把每个数组元素当作字符串并按字母表顺序排序[Shanghai, New York, Mumbai, Buenos Aires].sort(); // [Buenos Aires, Mumbai, New York, Shanghai]对纯英文ASCII字符串这个结果是符合预期的。但当你尝试排序一个包含非 ASCII 字符如重音字母é、á、ú的数组时就会得到一个奇怪的结果[é, a, ú, c].sort(); // [c, e, á, ú] // 错序不符合任何自然语言的字母顺序再看两个真实的语言场景// 西班牙语 [único,árbol, cosas, fútbol].sort(); // [cosas, fútbol, árbol, único] // 错误顺序 // 德语 [Woche, wöchentlich, wäre, Wann].sort(); // [Wann, Woche, wäre, wöchentlich] // 错误顺序在西班牙语中árbol应排在cosas之前在德语中Wann应排在wäre之前、wöchentlich之前。但原生排序完全打乱了语言习惯。为什么会这样从语言规范与实现机制可以推断不带比较函数调用sort()时引擎会把每个元素转换为字符串然后逐字符按 UTF-16 码元code unit的数值大小比较。重音字母的 Unicode 码点远大于普通 ASCII 字母例如é的码点是 U00E9大于a的 U0061 和c的 U0063于是é、á、ú这类字符全部被排到了a、c之后看起来就是乱序。简单说原生sort()只懂英文或者说只懂纯码点排序不理解任何语言的重音规则、大小写规则与字母扩展规则。解决方案一使用String.prototype.localeCompare()localeCompare()是字符串实例上的方法由 ECMAScript 国际化 APIECMA-402提供。它按指定区域的语言规则比较两个字符串返回一个负数、零或正数正好可以作为sort()的比较函数[único,árbol, cosas, fútbol].sort(function (a, b) { return a.localeCompare(b); }); // [árbol, cosas, fútbol, único] [Woche, wöchentlich, wäre, Wann].sort(function (a, b) { return a.localeCompare(b); }); // [Wann, wäre, Woche, wöchentlich]可以看到两组数据都恢复了正确的语言排序árbol排到了最前Wann也排到了德语序列的正确位置。解决方案二使用Intl.CollatorIntl.Collator是同一个国际化 API 提供的更专门的排序器对象。它的compare属性是一个可直接传入sort()的稳定比较函数写法更简洁[único,árbol, cosas, fútbol].sort(Intl.Collator().compare); // [árbol, cosas, fútbol, único] [Woche, wöchentlich, wäre, Wann].sort(Intl.Collator().compare); // [Wann, wäre, Woche, wöchentlich]输出与localeCompare()完全一致但省去了每次比较时临时创建函数调用的开销。定制区域locale与比较规则这两种方法都带有各自的可配置参数以便适配不同的语言环境。两个 API 都接受locales与options两个参数这是它们最实用的部分locales区域标识例如es西班牙语、de德语、fr法语、zh-Hans-CN简体中文。不传时使用运行环境的默认区域。// 指定西班牙语区域排序 [único, árbol, cosas, fútbol] .sort((a, b) a.localeCompare(b, es)); // 用 Collator 指定德语区域 const germanCollator new Intl.Collator(de); [Woche, wöchentlich, wäre, Wann].sort(germanCollator.compare);options比较规则常用配置包括sensitivity决定比较时是否区分大小写与重音取值如base、accent、case、variant和usage取值sort或search等。例如sensitivity: base意味着忽略大小写与重音差异只按基本字母比较// 忽略大小写与重音进行排序 [é, E, e, a, A].sort((a, b) a.localeCompare(b, fr, { sensitivity: base }));这两组参数让localeCompare()与Intl.Collator不仅能正确排序还能按业务需求调整排序到多细的粒度。性能考量大批量字符串优先使用Intl.Collator根据原文档引述的官方性能说明当需要比较大量字符串时Intl.Collator更快。原因从实现结构上可以理解Collator是一个可复用的排序器对象其compare函数被一次性构建后反复调用而localeCompare每次调用都可能重新解析区域规则。因此排序少量数据如几个下拉选项两者皆可localeCompare写法直观排序成百上千条字符串如用户列表、商品名、城市列表优先创建一次Intl.Collator并复用其compare能明显减少重复开销。综合实战去重 按语言排序的完整示例本仓库的另一篇 JS Tips第 26 篇过滤并排序字符串列表演示了先filter去重、再sort排序的组合用法。把两者结合并换成localeCompare/Intl.Collator作为比较器就是一个处理多语言数据列表的完整方案const names [úrsula, Álvaro, carlos, úrsula, Érika, álvaro]; // ES6 写法去重后按西班牙语规则排序 const sorted [...new Set(names)] .sort((a, b) a.localeCompare(b, es)); console.log(sorted); // [álvaro, Álvaro, carlos, Érika, úrsula]顺序按区域规则确定再进一步用Intl.Collator预构建比较器适合数据量大、需要反复排序的场景const collator new Intl.Collator(es); const sorted [...new Set(names)].sort(collator.compare);仓库内的印证与扩展阅读本文对应的原始文档英文原版另有简体中文、繁体中文、西班牙语等多语言版本可对照阅读README.md 的 Tips 列表将本篇列为第 04 号技巧同系列的排序/过滤主题还可参考第 26 篇过滤与排序字符串列表若想进一步掌握字符串包含判断可阅读第 15 篇indexOf 的简化用法其中也涉及字符串比较的边界场景帖子格式规范参见 POST_TEMPLATE.md。小结当你要排序的字符串数组并非纯英文时务必不要直接使用裸的array.sort()小数据量使用a.localeCompare(b)必要时传入locales与options大数据量预构建Intl.Collator并复用其compare性能更优多语言产品为每种目标语言显式指定区域标识避免依赖运行环境的默认区域导致结果不一致。记住这条经验排序含重音字符的字符串时使用localeCompare()或Intl.Collator才能得到符合语言习惯的排列结果。赞分享教程【免费下载链接】jstipsThis is about useful JS tips!项目地址https://gitcode.com/gh_mirrors/js/jstips点击查看免费下载相关推荐jstips 实战 04带重音符号字符串的正确排序——localeCompare 与 Intl.Collator 全面解析jstips 实战 04带重音符号字符串的正确排序——localeCompare 与 Intl.Collator 全面解析 本文是 jstips 仓库第 04教程jstips 实战 04带重音符号的字符串排序——localeCompare 与 Intl.Collator 完全指南jstips 实战 04带重音符号的字符串排序——localeCompare 与 Intl.Collator 完全指南 本文源自 jstips https:/教程TypeScript 类型挑战用 Union 与模板字符串实现 CheckRepeatedChars判断字符串是否含重复字符TypeScript 类型挑战用 Union 与模板字符串实现 CheckRepeatedChars判断字符串是否含重复字符 导读 本篇文章围绕 type示例工程创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表