iOS 字符串搜索匹配拼音或拼音首字母算法實現(xiàn)

概述

使用拼音或拼音首字母進行搜索匹配,可以減少輸入,提高交互效率。在查找和搜索時帶來效率提升,在 iOS中,app本地搜索功能,需要實現(xiàn)拼音或拼音首字母匹配。本文從算法流程及實現(xiàn)中遇到的問題來闡述,并附上源碼實現(xiàn)。

需求

輸入拼音或拼音首字母,匹配對應漢字字符。若原字符串中對應有非漢字,則進行原始字符匹配。
比如:中華民族 ,輸入:zhonghuazh,匹配輸出:中華;zhan勝困難,輸入:zhanshengzhans,匹配輸出:zhan勝;
為了減少用戶的輸入,支持不完全輸入搜索。即最后一個拼音不用完整輸入,比如::中華民族 ,輸入:zhongh,匹配輸出:中華。

算法設計

首先,需要將漢字轉化為拼音
蘋果 CFString.h 中提供了將字符轉化為帶音標的拼音的函數(shù):
CFStringTransform(CFMutableStringRef string, CFRange *range, CFStringRef transform, Boolean reverse)
可以將漢字先轉化為帶音標的拼音,然后將音標去除:
- (NSString *)stringByFoldingWithOptions:(NSStringCompareOptions)options locale:(nullable NSLocale *)locale

第2步,進入匹配流程

  1. 準備工作:
    由于中文拼音的復雜性,以及原始字符串可能是中英文混合字符串,所以構造一個輔助數(shù)組,存儲每個字符的拼音;另外構造一個數(shù)組,存儲每個字符的首個拼音字母。
    將轉化后的拼音拼接在一起,組成一個完整的字符串拼音
    用圖表示的流程如下:


    生成拼音及拼音首字母

根據(jù)原始字符串得到拼音、拼音首字母及單個字符拼音組成的數(shù)組。
比如,只含有漢字、漢字與英文混合等樣式的字符串經過轉換,可以得到下列結果。

字符串(M) 拼音(Str) 首字母(LA) 拼音組成的數(shù)組(SA)
夜來風 YELAIFENG YLF YE,LAI,FENG
ALC花 ALCHUA ALCH A,L,C,HUA
半夢半醒 BANMENGBANXING BMBX BAN,MENG,BAN,XING

2.2 正式匹配
首先將待匹配的字符串轉換為大寫,通過待匹配的字符串(M)的首字母,去步驟 2.1 中得到的拼音首字母字符串(LA)中定位到位置i,然后借助拼音數(shù)組SA,尋找第i個位置的字符串,從第i個位置開始尋找最少個數(shù)(len)的字符串,拼接組成的字符串以M為起始字符串。
尋找成功,則匹配的字符串位于原始字符串i,長度為len;若拼接子字符串長度大于或等于待匹配字符串,或直到LA最后一個字符串,仍然找不到拼接的字符串能以M為起始字符串。則需要在拼音首字母字符串(LA)中重新定位,在位置i后尋找新的位置,重新上一個步驟。直至遍歷到LA的末尾字符,仍然沒有找到,則匹配失敗。
以2.1中的表最后一個字符串為例,搜索: banxing.

步驟 操作內容
1 banxing 轉換為大寫-> BANXING
2 BANXING 取首字母 -> B
3 BMBX 中匹配 B,得到位置NSRange r1 =(0,1)
4 (BAN,MENG,BAN,XING)第一個位置起,匹配含有 BANXING 的最短拼接字符串
4.1 取第一個拼音字符串,一個元素,得到 BAN,不包含BANXING
4.2 取第一個拼音字符串,2個元素,得到 BANMENG,不包含BANXING的前綴
4.3 判斷拼接的拼音子字符串BANMENG長度,為7,與BANXING的長度相等,結束此輪匹配
5 BMBXBFS 中,從第一個B后面,即第二個位置開始匹配 B,得到位置NSRange r2 =(1,1),新的起始位置為 r1.location+r2.location+r2.length=0+1+1=2
5.1 (BAN,MENG,BAN,XING)第2個位置起,匹配含有 BANXING 的最短拼接字符串
5.2 取第2個拼音字符串(一個元素),得到 BAN,不包含BANXING
5.3 取第一個拼音字符串,2個元素,得到 BANXING,
5.4 判斷拼接的拼音子字符串 BANXING 的長度,與待匹配字符串長度一致,繼續(xù)。
5.5 拼接的 字符串 BANXING 包含 BANXING 的前綴。 匹配的長度為2
5.6 返回原字符串r3=(2,2),即從第2個元素開始2個長度的字符串。即: 半醒
  1. 校驗并匹配
    根據(jù)生成的拼音或拼音首字母,當待匹配字符串在上述2個字符串中其中一個里面存在時,再進行匹配.

遇到的問題

之前,借助漢字轉拼音的第三方庫[NSString+Extensional],將整個原始字符串通過函數(shù)pinyinForSort作為整體轉換得到拼音,由于該函數(shù)返回的字符串,相鄰的漢字拼音使用空格' '分割,因此可以進一步使用NSString 的函數(shù):

- (NSArray<NSString *> *)componentsSeparatedByString:(NSString *)separator

得到拼音字符數(shù)組SA。不過針對中英文混合的字符串,相鄰的英文和中文會連在一起,中間沒有空格分割。導致使用該庫的函數(shù)firstLettersForSort得到的拼音首字母字符串FS長度與SA長度不一致。給后續(xù)匹配造成困難。
下標列出全部轉換為大寫后的結果:

庫函數(shù)結果 修改后函數(shù)結果
原始字符串 YDB4測試服7 YDB4測試服7
字符串拼音 YDB4CESHIFU7 YDB4CESHIFU7
字符串拼音首字母 YDB4CSF7 YDB4CSF7
字符串拼音數(shù)組 YDB4CE,SHI,FU7 Y,D,B,4,CE,SHI,FU,7

詳細代碼

將代碼放在了Github spellMatch,若有不足,歡迎指正。有幫助的話,不吝star。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • 前言 最先接觸編程的知識是在大學里面,大學里面學了一些基礎的知識,c語言,java語言,單片機的匯編語言等;大學畢...
    oceanfive閱讀 3,375評論 0 7
  • 概要 64學時 3.5學分 章節(jié)安排 電子商務網站概況 HTML5+CSS3 JavaScript Node 電子...
    阿啊阿吖丁閱讀 9,799評論 0 3
  • 第5章 引用類型(返回首頁) 本章內容 使用對象 創(chuàng)建并操作數(shù)組 理解基本的JavaScript類型 使用基本類型...
    大學一百閱讀 3,674評論 0 4
  • 官網 中文版本 好的網站 Content-type: text/htmlBASH Section: User ...
    不排版閱讀 4,707評論 0 5
  • 可愛的小山羊 奶奶家養(yǎng)了許多羊,其中有一只老山羊在今年夏天時,生下了一只可愛的小山羊。 小山羊剛生下來時還閉...
    冬天雪花紛紛飛揚閱讀 225評論 1 1

友情鏈接更多精彩內容