神級程序員JavaScript300行代碼搞定漢字轉拼音

2017/08/16

一. 漢字轉拼音的現狀

首先應該說,漢字轉拼音是個強需求,比如聯繫人按拼音字母排序/篩選;比如目的地(典型如機票購買)

按拼音首字母分類等等。但是這個需求的解決方案,但好像沒聽過什麼巧妙的實現(特別是瀏覽器端),大概都需要一個龐大的字典。

具體到JavaScript,查查github和npm,比較優秀的處理漢字轉拼音的庫有pinyinpinyinjs,可以看到,兩者都自帶了龐大的字典。

這些字典動輒幾十上百KB(有的甚至幾MB),想在瀏覽器端使用還是需要一些勇氣的。所以當我們碰到漢字轉拼音的需求,也不怪我們第一反應就是拒絕需求(或者服務端實現)。

現在,如果我告訴你可以瀏覽器端 300 行代碼實現漢字轉拼音,是不是不可置信?

二. 從安卓4.2.2聯繫人代碼說起

再次強調這篇博客——利用Android源碼,輕鬆實現漢字轉拼音功能。

今天和大家分享一個從Android系統源代碼提取出來的漢字轉成拼音實現方案,只要一個類,560多行代碼就可以讓你輕鬆實現漢字轉成拼音的功能,且無需其他任何第三方依賴。

是不是打破了你的思維定勢:難道有什麼強大的演算法可以拋棄字典?

第一遍看完博客,稍有些失望,並沒有什麼演算法解析,只是介紹了從安卓代碼發現的這幾百行代碼。第二遍時帶著移植到JavaScript的想法閱讀代碼,算是弄懂了原理,於是開始了踩坑的移植之旅。

三. 手把手教你 300 行JavaScript代碼實現漢字轉拼音

首先直指核心:為什麼有漢字轉拼音必須有龐大字典的思維定勢?

因為漢字的排布和拼音並有什麼關聯,比如在漢字區間一-鿿,前一個可能是ha,后一個可能就是ze,沒有辦法從漢字的unicode關聯到拼音,所以只能有一個龐大的字典記錄每個漢字(或常用漢字)的拼音。

但是,假設我們可以把所有漢字按拼音排序,比如按'A', 'AI', 'AN', 'ANG', 'AO', 'BA',...,'ZUI', 'ZUN', 'ZUO'排序,那麼,我們只需要記住每個相同拼音的漢字隊列的第一個漢字就好了。那麼,所需要的字典就會很小(覆蓋所有拼音即可,拼音數量本身不多)。

現在,難點就是把漢字按拼音排序了。很幸運,ICU/本地化相關的API提供了這個排序API(如果沒有方便的排序/比較方法,那麼本篇文章可能就不會出現了)。

所以,這就是為什麼 300 行可以實現漢字轉拼音:Intl.Collator API:Intl.Collator內部實現了本土化相關的字元串排序。我們通過Intl.Collator.prototype.compare可以把所有漢字 基本 按照拼音來排序。

邊界漢字表:記錄了排序的邊界點。該漢字表的每個漢字都是排序后相同拼音的漢字集合的首個漢字(Each unihans is the first one within same pinyin when collator is zh_CN)。

如果想要更多的企業求職加分項目,案例,學習方法可以來一下我的前端群657-137-906,每天都會精挑細選一個特效,項目出來詳細講解,分享!包括答疑解惑!

說到這裡,可能仍然有沒說清楚的地方,所以直接上一段代碼:

有興趣的同學可以執行node --icu-data-dir=node_modules/full-icu 上面的腳本.js看看,然後看看是不是得到了 基本 按照拼音排序的漢字表。

這裡有幾點要注意:

我再次加粗了 「基本」 ,因為我們得到的漢字列表並沒有完全按照拼音來排序,中間偶爾有一些其它拼音的漢字插入,這點在製作 邊界表 時要額外注意。

上面腳本里得出的表是所有漢字的排序,其中有些和安卓代碼里HanziToPinyin.java的表有不同,所以需要更新HanziToPinyin.java的表。(從Java轉到JavaScript的最大的坑和工作量:更正邊界表)

相信大家都看到了核心代碼:const COLLATOR = new Intl.Collator(['zh-Hans-CN'])Intl.Collator(這裡指定locale是zh-Hans-CN)正是能把漢字按拼音排序的關鍵,它是按locale-specific順序,排序字元串的Internationalization API。

執行腳本時請先npm i full-icu,這個依賴會自動安裝缺失的中文支持並提示如何指定ICU數據文件來執行腳本。

1. ICUICU即International Components for Unicode,為應用提供Unicode和國際化支持。

ICU is a mature, widely used set of C/C++ and Java libraries providing Unicode and Globalization support for software applications. ICU is widely portable and gives applications the same results on all platforms and between C/C++ and Java software.

並且 ICU 提供了本地化字元串比較服務(Unicode Collation Algorithm + 本地特定的比較規則):

Collation: Compare strings according to the conventions and standards of a particular language, region or country. ICU's collation is based on the Unicode Collation Algorithm plus locale-specific comparison rules from the Common Locale Data Repository, a comprehensive source for this type of data.

在現代瀏覽器上,一般ICU內置了對用戶本地語言的支持,我們直接使用即可。

但對node.js來說,通常情況下,ICU只包含了一個子集(通常是英語),所以我們需要自行添加對中文的支持。一般來說,可以通過npm install full-icu安裝full-icu來安裝缺失的中文支持。(參見上面node --icu-data-dir=node_modules/full-icu)。

2. Intl API上一小節應該基本講清楚了國際化/本地化相關的知識,這裡再補充一下內置API的使用。怎麼查看用戶語言和Runtime是否支持這個語言?Intl.Collator.supportedLocalesOf(array|string)

返回包含支持(不用回退到默認locale)的locales的數組,參數可以是數組或字元串,為想要測試的locales(即BCP 47 language tag)。

構造Collator對象和排序字元串

通過Intl.Collator.prototype.compare,我們可以按語言指定的順序來排序字元串。而中文中,這個排序恰好絕大多數都是按拼音的順序來的,'A', 'AI', 'AN', 'ANG', 'AO', 'BA', 'BAI', 'BAN', 'BANG', 'BAO', 'BEI', 'BEN', 'BENG', 'BI', 'BIAN', 'BIAO', 'BIE', 'BIN', 'BING', 'BO', 'BU', 'CA', 'CAI', 'CAN', ...,這正是我們上面提到的漢字轉拼音的關鍵。

四. 邊界表更正

顯然,這個邊界表是有問題的,需要更正。

我們可看到,大部分的漢字被轉成了qing,可見,qing這個拼音對應的漢字有問題。

找到這個漢字,是 '狅'/'狅',加上前後各一個字,['親', '狅', '芎']/["親", "狅", "芎"]

搜索,'狅'/'狅'可以讀qing,但現在多讀kuang,這應該就是錯誤的原因了。

根據最初得到那張所有漢字的排序表,qing的第一個漢字是'靑'/'靑'

改動后,轉換失敗的只剩104了。

本文由 一點資訊 提供 原文連結

立即按讚,感謝大大無私地分享
寫了5859808篇文章,獲得4231
Line

熱門推薦

精彩推薦

時值秋天,感冒咳嗽的人增多,而且咳嗽纏綿難愈,在中醫看來是風邪未除的表現。推薦服用普世真 草膏,這是一款純中藥熬制的膏方,不含糖,無添加,無副作用,對感冒咳嗽、慢性咽炎有特效,我經常給那些打針輸液效...
9月10日,「洪凌天地四時行」繪畫作品展在國家大劇院東展覽廳啟幕。此次展覽將持續至9月23日,匯聚了著名畫家洪凌先生20余幅新近創作的油畫與水墨畫,其中受國家大劇院之邀創作的巨幅油畫《四季交響》更是首次公...
我們都知道中醫能通過面相來診斷健康,其原理就是通過觀察面部的一些異常情況來判斷身體的健康情況,那麼面部哪些地方能反應健康情況呢? 面部最能反應健康狀況的10個部位 臉色臉色過於蒼白,顯示飲食中缺乏葉酸...
長江商報消息 各大拍賣中西洋古董成交率不斷攀升,不少人選擇古典油畫、飾品來點綴和投資□本報記者 紀文君昔日的熱播英劇《唐頓莊園》,以19世紀的傢具、典雅的飾物,掀起一股復古風。在古董藝術品的風潮中里,最...
黑龍江省七台河市勃利縣人民檢察院
我們可能知道許多古錢幣但是也有一些古錢幣是我們不知道的,可能你知道的古錢幣僅僅冰山一角,也可以說我們發現的古錢幣僅僅冰山一角,還有許多古錢到現在都沒發現,等著我們去發現,也有一些現已發現了但是人們...
近十餘年來,國家博物館新入藏青銅器、佛造像、書畫碑帖、陶瓷、傢具、漆器、玉器等珍貴文物藏品達40多萬件!這些曾散落民間或流失海外的文物很多是國之重器。▌宗邦重器 作為禮器,青銅容器是貴族地位的標誌,家...
Uber大股東不死心 仍尋求讓惠特曼出任CEO並已會談惠特曼據CNBC網站北京時間8月23日報道,知情人士稱,惠普企業CEO梅格·惠特曼(Meg Whitman)仍被Uber最大股東視為公司新任CEO的候選人之一。惠特曼曾在7月27日發表...
右坐者秦康祥秦康祥(1914—1968年)原名仲祥,后改名康祥,字彥沖,浙江寧波人,寓居上海。其曾祖秦君安、祖父秦際瀚、父親秦偉楚三代均為在上海經商的寧波人士。幼時進馮君木先生在寧波后樂園開辦的國學社學習經...
則回覆