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

概述

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

需求

輸入拼音或拼音首字母,匹配對應(yīng)漢字字符绿饵。若原字符串中對應(yīng)有非漢字欠肾,則進行原始字符匹配。
比如:中華民族 拟赊,輸入:zhonghuazh,匹配輸出:中華刺桃;zhan勝困難,輸入:zhanshengzhans,匹配輸出:zhan勝吸祟;
為了減少用戶的輸入瑟慈,支持不完全輸入搜索。即最后一個拼音不用完整輸入屋匕,比如::中華民族 葛碧,輸入:zhongh,匹配輸出:中華

算法設(shè)計

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

第2步,進入匹配流程

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


    生成拼音及拼音首字母

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

字符串(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 正式匹配
首先將待匹配的字符串轉(zhuǎn)換為大寫涝婉,通過待匹配的字符串(M)的首字母哥力,去步驟 2.1 中得到的拼音首字母字符串(LA)中定位到位置i,然后借助拼音數(shù)組SA,尋找第i個位置的字符串墩弯,從第i個位置開始尋找最少個數(shù)(len)的字符串吩跋,拼接組成的字符串以M為起始字符串。
尋找成功渔工,則匹配的字符串位于原始字符串i锌钮,長度為len;若拼接子字符串長度大于或等于待匹配字符串引矩,或直到LA最后一個字符串梁丘,仍然找不到拼接的字符串能以M為起始字符串侵浸。則需要在拼音首字母字符串(LA)中重新定位,在位置i后尋找新的位置氛谜,重新上一個步驟掏觉。直至遍歷到LA的末尾字符,仍然沒有找到值漫,則匹配失敗澳腹。
以2.1中的表最后一個字符串為例,搜索: banxing.

步驟 操作內(nèi)容
1 banxing 轉(zhuǎn)換為大寫-> 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的長度相等集畅,結(jié)束此輪匹配
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個字符串中其中一個里面存在時程拭,再進行匹配.

遇到的問題

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

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

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

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

詳細代碼

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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末鞭盟,一起剝皮案震驚了整個濱河市圾结,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌齿诉,老刑警劉巖筝野,帶你破解...
    沈念sama閱讀 212,454評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異粤剧,居然都是意外死亡歇竟,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評論 3 385
  • 文/潘曉璐 我一進店門抵恋,熙熙樓的掌柜王于貴愁眉苦臉地迎上來焕议,“玉大人,你說我怎么就攤上這事弧关≈寻玻” “怎么了?”我有些...
    開封第一講書人閱讀 157,921評論 0 348
  • 文/不壞的土叔 我叫張陵梯醒,是天一觀的道長宽堆。 經(jīng)常有香客問我,道長茸习,這世上最難降的妖魔是什么畜隶? 我笑而不...
    開封第一講書人閱讀 56,648評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮号胚,結(jié)果婚禮上籽慢,老公的妹妹穿的比我還像新娘。我一直安慰自己猫胁,他們只是感情好箱亿,可當我...
    茶點故事閱讀 65,770評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弃秆,像睡著了一般届惋。 火紅的嫁衣襯著肌膚如雪髓帽。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評論 1 291
  • 那天脑豹,我揣著相機與錄音郑藏,去河邊找鬼。 笑死瘩欺,一個胖子當著我的面吹牛必盖,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播俱饿,決...
    沈念sama閱讀 39,090評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼歌粥,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了拍埠?” 一聲冷哼從身側(cè)響起失驶,我...
    開封第一講書人閱讀 37,817評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎械拍,沒想到半個月后突勇,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡坷虑,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,592評論 2 327
  • 正文 我和宋清朗相戀三年甲馋,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迄损。...
    茶點故事閱讀 38,724評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡定躏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出芹敌,到底是詐尸還是另有隱情痊远,我是刑警寧澤,帶...
    沈念sama閱讀 34,409評論 4 333
  • 正文 年R本政府宣布氏捞,位于F島的核電站碧聪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏液茎。R本人自食惡果不足惜逞姿,卻給世界環(huán)境...
    茶點故事閱讀 40,052評論 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望捆等。 院中可真熱鬧滞造,春花似錦、人聲如沸栋烤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽明郭。三九已至买窟,卻和暖如春丰泊,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蔑祟。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評論 1 266
  • 我被黑心中介騙來泰國打工趁耗, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人疆虚。 一個月前我還...
    沈念sama閱讀 46,503評論 2 361
  • 正文 我出身青樓,卻偏偏與公主長得像满葛,于是被迫代替她去往敵國和親径簿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,627評論 2 350

推薦閱讀更多精彩內(nèi)容