汉字转拼音的浏览器端实现

您所在的位置:网站首页 ie拼音怎么拼写 汉字转拼音的浏览器端实现

汉字转拼音的浏览器端实现

2023-03-31 19:29| 来源: 网络整理| 查看: 265

背景介绍

汉字转拼音,首先想到的是准备一张超大的汉字到拼音的映射表,我们先来算下这张映射表有多大。

基本汉字一共有 20902 个,对应 Unicode 的编码范围是 4E00-9FA5,其中包括了朝鲜文汉字和日文汉字,所以也称为中日韩统一表意文字(英语:CJK Unified Ideographs)。有些汉字是多音字,如果每个汉字只取一种读音,这张汉字到拼音的映射表有 329KB,按拼音排序后,gzip 后的文件大小,最小可以减少至 46.7KB(不排序的话有 72.4KB,压缩算法对有序字符串有更高的压缩率)。所以,在浏览器中直接使用这个映射表文件的成本比较大,一般汉字转拼音都在后端处理。

今天向大家介绍一种在浏览器端实现的汉字转拼音方法,实现文件 gzip 后只有 2.7KB(修正 Safari 浏览器后的大小是 3.9KB),支持所有的基本汉字(实现时去掉了浏览器不识别的汉字,比如在 Chrome 浏览器中去掉的汉字有:兙、兡、嗧、桛、烪、瓧、瓰、瓱、瓼、甅),体积和效率都有保证。

注意,本实现不支持多音字,也不支持声调。在浏览器端使用的时候,由于输入法一般也打不出声调来,所以使用场景应该不受影响。另外映射表和代码也可以自己实现,以便满足个性化需求。实现原理

在 JavaScript 中,字符串 String 有个方法叫 localeCompare,它可以对汉字按拼音进行排序,代码如下:

let name = '网易杭州'; let sortedName = name.split('').sort((a, b) => { // 如果我没记错的话,早期的这个方法并不需要第二个参数 return a.localeCompare(b, 'zh-CN'); }).join(''); console.log(sortedName); // 输出 '杭网易州'

该方法在 Chrome、Safari、Firefox、IE11 等浏览器中都可以使用。利用这个方法,就可以知道任意两个汉字的相对顺序。

汉字虽然有 20000 多个,但汉字拼音是有限的,一共有 410 多个拼音,这些拼音把所有的汉字划分成了一个个的区块:

每一个汉字,它都会落在上图的某个区块中。我们取每个拼音第一个出现的汉字:

我们的目的是计算汉字的拼音,将目标汉字与上图的每个汉字使用 localeCompare 方法进行比较,每次比较就只有三种结果,要么在被比较汉字的前面,要么在被比较汉字的后面,还有一种情况是正好和被比较汉字相同,通过一轮比较,我们就可以得知目标汉字落在了哪个区块,而该区块对应的拼音是事先准备好的,所以也就得到了目标汉字对应的拼音。因为上图组成的汉字列表,是按拼音排序的,也就是它是一个有序列表,那么就可以使用二分查找法,快速地进行定位。二分查找的时间复杂度是 O(log n),410 个拼音,最多比较 9 次,效率有了保证。

我们举个具体的例子,假设目标汉字为“哀”,通过比较我们发现它排在“哎”后面,排在“安”前面,“安”是“an”的第一个拼音汉字(每种拼音相同的汉字可能有很多个,第一个拼音汉字,本文是指每种拼音第一个出现的汉字),它前面肯定是“ai”区块(如果不取第一个拼音汉字,这种情况还是无法确定目标汉字到底是在“ai”区块还是在“a”区块,因为每个区块有 N 个汉字,这些汉字本身也有相对顺序;当然,我们也可以取最后一个拼音汉字作为比较汉字),所以“哀”的拼音肯定是“ai”了。

实现原理就这么简单,非常巧妙。下面介绍如何得到这张汉字拼音映射表。

汉字拼音映射表

看到这里,有同学可能会说这还不简单,找本《现代汉语词典》就行了,但这种手工方式,保守估计也要花 1 天时间的工作量,效率低下姑且不说,毕竟这是一次性劳动,最要命的是,有些汉字在《现代汉语词典》的顺序和在浏览器中的顺序是不一样的。

既然我们已经知道了汉字的 Unicode 编码范围,只要一个循环,就能得到所有的汉字,再调用提供汉字到拼音转换的第三方 API 接口(比如这个网站:中文转拼音,每次可以转换 3000 个汉字),这样就能很快得到所有汉字以及对应拼音的映射表。再利用 localeCompare 方法,对这张表的汉字排序,这样就能得到有序的所有汉字拼音表。由于我们只取每种拼音的第一个汉字,再写段很简单的代码就可以提取出来了。

下面这段获取所有汉字及相应拼音的示例代码,可以在 Chrome 插件中(在插件中接口可以跨域调用)运行得到结果:

let start = 0x4e00, end = 0x9FA5; let result = {}; let get = function () { if (start > end) { // 此时 result 就包含了所有的汉字以及相应的拼音 console.log(JSON.stringify(result)); return; } let arr = [] for (let i = start; i var COLLATOR = new Intl.Collator(['zh-CN']) COLLATOR.compare('网', '易') // 输出 -1

具体实现代码已托管在 github 上面:pinyin.js 。

应用场景

看到这里,有同学可能会有疑问,汉字转拼音,在浏览器端有什么应用场景?

其实可以反过来使用。比如在 NEI 接口管理平台 网站中,在项目的接口列表页面有个搜索功能,可以按照用户输入的拼音在前端搜索。接口列表是一次性全部加载的,此时就可以先把相关内容转换成拼音,然后和用户输入的拼音进行对比即可。

吐槽

我们已经发现,在 Chrome 和 Safari 中,很多汉字的拼音是不对的,这里也吐槽一下中文语言包的制作者,我分析了下,大概有这么几种情况:

有些多音字选择了不常见的读音,比如“沈”,在 Chrome 中是“chen”,而不是常见的“shen”,又比如“呵”,在 Safari 中念“a”读字读半边,这种例子有很多,比如“碡”,念成了“du”(正确的读音是 zhóu),“聒”念成了“gua”(正确的读音是 guō)纯粹乱读,Safari 中有很多,比如“鼰”,念成了“nian”(正确的读音是 jú),“罉”,念成了“cang”(正确的读音是 chēng),“伝”,念成了“chuan”(正确的读音是 yún),“枡”,念成了“dou”(正确的读音是 shēng)

根据从上面的分析,我猜测一下:Chrome 的中文语言包制作者应该是一位在国外长大的中国人,Safari 的中文语言包制作应该是一位主修中文专业的外国人。还有一种可能是这两位同学都买到了一本假的汉语词典,并且,Safari 的这位同学是从街边小摊买的。

最后

文章就写到这里,最后发个广告,网易杭州长期求资深前端,欢迎简历。

参考资料本方案并非原创,而是参考了 pinyin 的实现,并在它的基础做了一点微小的工作。如文中所说,该方案是从 Android 源码中扒出来的。


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3