Skip to content

解决 JavaScript 中文排序的痛点

在 JavaScript 中,对中文内容进行排序一直以来都是个棘手的问题。如果直接调用 sort 方法,结果可能并不符合我们的预期。

一、问题分析

以下是一个需要排序的中文数组:

js
const names = ["张三", "李四", "王五", "赵六", "孙七"];

直接调用 names.sort(),得到的结果如下:

js
['孙七', '张三', '李四', '王五', '赵六']

显然,这不是我们期望的排序顺序。原因是sort方法默认按字符串的 Unicode 编码进行排序。我们来看一下这些字的 Unicode 值:

js
"张".charCodeAt(0); // 24352
"李".charCodeAt(0); // 26446
"王".charCodeAt(0); // 29579
"赵".charCodeAt(0); // 36213
"孙".charCodeAt(0); // 23385

可以看到,"孙" 的 Unicode 编码小于 "张",因此在排序结果中排在前面。

二、目的

为了实现符合中文拼音规则的排序,我们需要一种更合理的排序方法。

三、使用 localeCompare 方法

localeCompare 是 JavaScript 中一个内置的字符串比较方法,允许指定语言环境来进行排序。在中文环境下,可以通过以下方式实现正确的中文排序:

1. 示例代码

js
const names = ["张三", "李四", "王五", "赵六", "孙七"];
names.sort((a, b) => a.localeCompare(b, 'zh-CN'));
console.log(names); 
// ['李四', '孙七', '王五', '张三', '赵六']

优点:

  • 简洁、无需额外依赖。
  • 能处理大多数中文排序需求。

注意事项:

  • localeCompare 是基于浏览器的语言设置和实现,某些情况下可能对多音字处理不够准确。例如,"重" 可以发音为 chóng 或 zhòng,导致排序结果可能不符合预期。

2. Local列表

Locale语言/区域说明
zh-CN中文(简体,中国)默认用于简体中文排序
zh-TW中文(繁体,台湾)繁体中文排序
zh-HK中文(繁体,香港)香港繁体中文排序
en-US英语(美国)美国英语
en-GB英语(英国)英国英语
fr-FR法语(法国)法国法语
fr-CA法语(加拿大)加拿大法语
de-DE德语(德国)德国语言环境
es-ES西班牙语(西班牙)西班牙西班牙语
es-MX西班牙语(墨西哥)墨西哥西班牙语
ja-JP日语(日本)日本日语环境
ko-KR韩语(韩国)韩国韩语
ru-RU俄语(俄罗斯)俄罗斯俄语
ar-SA阿拉伯语(沙特阿拉伯)沙特阿拉伯阿拉伯语
pt-PT葡萄牙语(葡萄牙)葡萄牙葡萄牙语
pt-BR葡萄牙语(巴西)巴西葡萄牙语
it-IT意大利语(意大利)意大利语言环境
hi-IN印地语(印度)印度印地语
th-TH泰语(泰国)泰国语言环境
vi-VN越南语(越南)越南语环境

使用示例:

js
const names = ["张三", "李四", "王五", "赵六", "孙七"];

// 简体中文排序
names.sort((a, b) => a.localeCompare(b, 'zh-CN'));
console.log(names);

// 繁体中文排序(香港)
names.sort((a, b) => a.localeCompare(b, 'zh-HK'));
console.log(names);

// 英语(美国)排序
const englishNames = ["apple", "Banana", "cherry"];
englishNames.sort((a, b) => a.localeCompare(b, 'en-US'));
console.log(englishNames);

注意事项:

  • 默认情况下,如果不指定 locale,localeCompare 会使用运行环境的默认语言环境。
  • 某些语言环境可能存在微小的排序差异,例如简体中文和繁体中文。
  • 浏览器或 JavaScript 引擎需要支持指定的语言环境,部分较旧环境可能不支持所有 locale 标识符。

四、使用拼音库处理多音字

对于多音字排序的场景,推荐使用开源拼音库(如 pinyin 或 pinyin-pro),它们可以准确地将中文转换为拼音并排序。

1. 示例代码(基于pinyin-pro)

  1. 安装pinyin-pro
bash
npm install pinyin-pro
  1. 使用拼音库进行排序:
js
import { pinyin } from 'pinyin-pro';

const names = ["张三", "李四", "王五", "赵六", "孙七", "重阳"];
names.sort((a, b) => pinyin(a, { toneType: 'none' }).localeCompare(pinyin(b, { toneType: 'none' })));
console.log(names); 
// ['李四', '孙七', '王五', '张三', '重阳', '赵六']

优点:

  • 准确处理多音字。
  • 提供灵活的配置(如带声调、不带声调等)。

缺点:

  • 增加了项目体积。

五、总结

  1. 对于一般中文排序需求,可以直接使用 localeCompare:
js
names.sort((a, b) => a.localeCompare(b, 'zh-CN'));
  1. 如果需要更精确的排序(包括多音字),可以使用拼音库:
js
import { pinyin } from 'pinyin-pro';
names.sort((a, b) => pinyin(a).localeCompare(pinyin(b)));

根据实际需求选择合适的方法,既能保持代码的简洁性,又能满足用户的体验需求。