多级权重与语言调整
Unicode 排序算法把每个字符映射为一组排序权重:主权重决定基础字母顺序(忽略重音与大小写),次权重解决重音差异,三级权重解决大小写差异,必要时还有更细一级处理标点与变体。比较时从高到低逐级判断,因而既能得到「a 与 á 相邻」的结果,也能支持忽略大小写的排序。此外每种语言可以按自身习惯调整权重:德语对 ä 的处理、瑞典语把 å 与 ö 排在字母表末尾、中文按拼音或笔画排序都属于语言相关规则。
基本信息
| 比较层次 | 主权重、次权重、三级权重,逐级比较 |
|---|---|
| 主权重 | 决定基础字母顺序,忽略重音与大小写 |
| 次权重 / 三级权重 | 分别处理重音差异与大小写差异 |
| 语言调整 | 各语言可自定义顺序,如中文拼音序与笔画序 |
| 常用实现 | ICU Collator、语言库的 collation、数据库 collation |
| 排序键 | 可预先计算并缓存,用于批量排序与索引 |
典型使用场景
- 通讯录与名单排序:中文按拼音或笔画,欧洲语言按本地习惯排列
- 数据库排序:ORDER BY 受列的 collation 影响,只改字符集不够
- 去重与分组:折叠大小写与重音后归组,需要排序规则配合
- 搜索建议:候选词按语言习惯排序,避免违背直觉的顺序
- 跨系统一致性:两端排序结果不同时,需明确各自使用的排序规则
排序示例
排序示例
# 码点排序与语言排序的差异:大写字母会排在所有小写字母之前
python -c "print(sorted(['b','A','a','B']))" # 码点序:A B a b
python -c "print(sorted(['b','A','a','B'], key=str.casefold))" # 忽略大小写的近似排序
# PyICU 用法示意:collator = icu.Collator.createInstance(icu.Locale('zh'))
# words.sort(key=collator.getSortKey)
# 未安装 PyICU 时可用数据库 COLLATE 或前端 Intl.Collator 兜底
# SQL 示例:SELECT name FROM t ORDER BY name COLLATE utf8mb4_zh_0900_as_cs;语言差异示例
| 语言 | 差异点 | 结果 |
|---|---|---|
| 德语 | ä 有字典序与电话簿序两类处理 | ä 可能等同 ae,也可能紧随 a |
| 瑞典语 | å ä ö 排在字母表末尾 | 与英语顺序明显不同 |
| 中文 | 拼音序与笔画序并行 | 同一组汉字的两种顺序完全不同 |
| 丹麦语 | 部分字母被视为独立字母 | 与邻国语言顺序不同 |
| 码点序 | 仅按码点数值比较 | 大写先于小写,重音字符脱离基字母 |
数据库的 collation 决定三件事:排序顺序、相等判断与索引行为。大小写不敏感的 collation 会让仅大小写不同的值判定为相等,从而影响唯一约束;修改 collation 会影响既有索引与业务语义,需评估后执行。
用字符串比较代替排序规则会产生「看起来没规律」的顺序:大写字母集中在小写之前、重音字符被排到远处、中文按码点乱序。对外展示的列表必须使用语言相关排序,中文场景至少要明确拼音或笔画。
排序键可以缓存:批量排序大量数据时,为每条记录预先计算排序键能降低重复比较成本;但排序键依赖排序规则版本,规则升级后需要重建,变更前应评估影响范围。