Skip to content
forked from xinglie/pinyin

汉字转拼音,支持20870个汉字,包含完整的多音字

License

Notifications You must be signed in to change notification settings

zhoudc1995/pinyin

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

汉字转拼音

支持20870个汉字,包含完整的多音字

使用示例

import Pinyin from 'pinyin'
console.log(Pinyin.getSpell('阿里巴巴欢迎您'));//[e,a],li,ba,ba,huan,ying,nin

因为“阿”是多音字,因此结果是 [e,a],li...这样子的,当您需要遇到多音字自已处理时,可以这样:

import Pinyin from 'pinyin'
Pinyin.getSpell('阿里巴巴欢迎您',function(charactor,spell){
    console.log(charactor,spell);
    return spell[1];
});

如果浏览器支持localeCompare

只有部分浏览器支持中文按拼音排序,如果浏览器支持则可以使用lc.js来获取拼音

压缩说明

网上常见的方案的都是字典表的思路,把所有汉字的拼音罗列一遍,我也是这样的思路。因为要达到能处理20870个汉字,同时要保障网络传输,本人想办法写了一个压缩算法,目前这个版本是压缩好的,带自解压功能,仅60-70kb,远远小于网上的其它方案的实现。

以下说明压缩思路:

汉字转拼音,最理想状态下是使用Stirng.prototype.localCompare了,把汉字按拼音排序,然后再查找汉字位于哪个区间,这种实现方案的代码量是最少的,但是由于这玩意并不是所有浏览器实现都一样,例如chrome早期的就不是按拼音排序,所以这个方案先放一边

那网上最常见的就是码表了,比如{"a":"吖阿啊..."},这种形式的最可靠稳定,但唯一不足的是码表太大,汉字的范围最常用的在 \u4e00-\u9fa5 这个区间里,其它区间的暂不考虑。这个区间有20928个汉字(后来经我资料查找,发现这个区间里有些汉字并没有对应的拼音,也有些汉字无法正常显示,所以被我精简到了20870个汉字了,当然网上也有只把常用的几千个汉字做为码表的)。

现在的问题就来了,如果把这2w多个汉字做为码表存在js文件里无异是非常大的,我们需要想办法压缩,而在压缩前我们还有些问题需要解决:

如果存放js代码的文件用utf-8来保存,那如果这个js被放在了gbk编码的页面上,并且script标签未指定charset utf-8,那么这个js中的汉字是会乱码的,所以需要编码,常用的是unicode成{"a":"\u5416\u963f\u554a..."},这样就不会有问题了。

如果用unicode编码,则2w多个汉字大概需要12w个字符表示(一个汉字6个字符)。这个量是非常大的,如何用最少的字符来表示这些汉字成了压缩的关键

我们知道每个汉字都可以用charCodeAt取到相应的数字编码,也可以用String.fromCharCode进行还原,例如:"我".charCodeAt(0);//20105;我们也可以用String.fromCharCode(20105)还原成"我"字,OK,到这一步,最小汉字是19968;最大是40896。如果把所有汉字用数字表示,则只需要10w个字符即可,1个汉字对应5个数字(当然,直接把这5位数字转16进制,则只需要4个就可以,2w多个汉字大约8w个字符,仍然很多)。

到这一步后,我给自已一个目标:能否用2个字符表示一个汉字?如果可以,那么大概只需要4w多字符就可以表示完,这个压缩比对10w个字符还是相当可喜的。

既然再压缩,那就把刚才的 汉字的数字 20105再进行压缩,这时候我采取的是进制转换,比如把它转成64进制等尽可能大的进制。如果转64进制,则2位64进制只能表示4096个汉字,这个太少了。我需要自已写一个大的进制转换,我把ascii码表重新拿出来,128个字符,除了不显示的,我挑中了从33到126之间的这些字符(除34,45,92三个外,因为我需要把程序发布到网上,别人可以复制粘贴之类的,所以需要可视字符),一共91个。那么91进制2位数可表示91*91=8281个,仍然不够。

回头再看汉字的区间,19968-40896 如果每个汉字都减去19968,则区间变成0-20928,如果把这个区间一分为2:0-10464 10465-20928,第二个区间每个汉字减去10465 则变成0-10463,至此2个区间各有1w个汉字,离我们的91进制2位表示的8281比较接近了。

假设我们用3个91进制的字符,则可以表示753571,表示2w个汉字绰绰有余,但这时候需要6w多个字符。如果我们使用91进制的2个字符,每个区间共有2000多个无法被表示,如果剩余的这2000多个用3个字符表示,我们会发现这2000多个的高位一样(xyz),都是'x';那么这时候大概需要4w加上2个6000,大概5w2k个字符即可表示完成。

当然,我们要对3位的高位给一个特殊的字符,这样我们再还原的时候就很方便还原了,这不是难事,忽略不讲

至此,我们就完成了压缩,最后的js大约共58kb

About

汉字转拼音,支持20870个汉字,包含完整的多音字

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • JavaScript 100.0%