本文探讨JavaScript中汉字排序的常见陷阱,指出原生localeCompare方法在跨平台环境下的不稳定性。通过构建自定义拼音字库并实现CompareStrings对象,提供了一套不依赖操作系统和浏览器内核的稳定排序方案,确保在非中文系统或Chrome等浏览器中也能获得一致的拼音排序结果。
汉字拼音排序的常见陷阱
在Web开发中,对汉字列表进行拼音排序是一项常见需求。
实现代码如下:
var list = [ '王', '张','李'];
list.sort(function (a, b) {
return a.localeCompare(b);
});localeCompare() 方法依据本地特定的排序规则比较两个字符串。
然而,依赖 localeCompare 进行汉字拼音排序存在明显的不可靠性:
1. 高度依赖中文操作系统环境。
2. 高度依赖浏览器内核的实现差异。
这意味着,若访问者使用非中文操作系统或非IE浏览器(如Chrome),往往无法得到预期的拼音排序结果。
--------------------------------------------------------------------------------
基于自定义字库的稳定排序方案
为解决上述问题,这里介绍一种替代方案,旨在提供更稳定的排序体验:
具体实现代码如下:
var CompareStrings = {
db: '吖阿啊锕錒嗄哎哀...袰襨鐢閪闏霻鶑', // 其中省略几万字
getOrderedUnicode: function (char) {
var originalUnicode = char.charCodeAt();
if (originalUnicode >= 0x4E00 && originalUnicode <= 0x9FA5) {
var index = this.db.indexOf(char);
if (index > -1) {
return index + 0x4E00;
}
}
return originalUnicode;
},
compare: function (a, b) {
if (a == b) { return 0;
}
// 这里可以根据具体需求来改写,目前的写法是把空字符串排在最后if (a.length == 0) { return 1; }
if (b.length == 0) { return -1; }
var count = a.length > b.length ? b.length : a.length;
for (var i = 0; i < count; i++) {
var au = this.getOrderedUnicode(a[i]);
var bu = this.getOrderedUnicode(b[i]);
if (au > bu) {
return 1;
} else if (au < bu) {
return -1;
}
}
return a.length > b.length ? 1 : -1;
}
}
// 重写系统原生的localeCompare
String.prototype.localeCompare = function (param) {
return CompareStrings.compare(this.toString(), param);
}如需获取完整代码,可通过以下链接下载:http://xiazai.jb51.net/201211/yuanma/js_pinyin_jb51.rar
实现原理详解
该方案的核心实现原理如下:
1. 构建按拼音排序的字库(db):可通过多种途径实现,例如结合JavaScript与C#。先由脚本枚举所有汉字,提交至C#后台排序后输出至前端。此步骤仅为准备工作,具体实现方式可灵活调整。
2. 确定字符大小(getOrderedUnicode):排序时需处理汉字及其他字符。通过判断字符是否为汉字来区别处理:若是汉字,则在预排序字库中查找其索引,加上Unicode字符集中首个汉字的位置,得到“校准”后的索引值;若非汉字,则直接返回其在Unicode中的原始索引。
3. 字符串比较(compare):逐字符比较两个字符串(以较短字符串长度为有效范围)。若发现a对应字符大于b,返回1;反之返回-1。
4. 长度处理:若在有效范围内比较未分胜负,则依据长度决定顺序。例如a='123',b='1234',较长的b应排在后面。
绿色通道: 好文要顶 关注我 收藏该文与我联系