拼音分詞拆解算法(用于判斷字符串是否是純拼音構(gòu)成,并分離出所有拼音陋葡,50行純原生代碼實(shí)現(xiàn))

廢話嗶嗶

都說算法是程序的靈魂亚亲,算法源于數(shù)學(xué),數(shù)學(xué)是描述宇宙萬物的語言腐缤,這話一點(diǎn)不假捌归,開發(fā)出身算法用的較少,回過頭看算法岭粤,用到了惜索,遞歸、循環(huán)剃浇、分支巾兆、分治、合并虎囚、取舍調(diào)優(yōu)的思想角塑,確實(shí)精彩,燒腦還挺有意思淘讥。
好的技術(shù)博客必須有做到有No BB,Show Code的干貨圃伶,也得有說明輔助理解,因此寫了這篇博客蒲列。

需求

  • 概括:將一個(gè)字符字符串窒朋,拆分單個(gè)的拼音,例如bianchengyuyan(編程語言)蝗岖,拆分成bian侥猩、cheng、yu抵赢、yan欺劳。如果是zhang1san(張1三)洛退,zhangssan(張s三),則返回空數(shù)組杰标。
  • 應(yīng)用場景:這算法并非百無一用,拼音分詞彩匕,詞義分析腔剂,品相判別等場景能夠用到。

成品代碼

<?php
/**
 * @function 返回拼音組合驼仪,由于冗長掸犬,單獨(dú)拆分出來,拼音手動(dòng)總結(jié)绪爸,可能存在遺漏
 * @return array
 */
function pinYinArr() {
    return [
        1 => ['a', 'e', 'm', 'n', 'o'],
        2 => ['ai','an','ao','ba','bi','bo','bu','ca','ce','ci','cu','da','de','di','du','en','er','fa','fo','fu','ga','ge','gu','ha','he','hm','hu','ji','ju','ka','ke','ku','la','le','li','lo','lu','lv','ma','me','mi','mo','mu','na','ne','ng','ni','nu','nv','ou','pa','pi','po','pu','qi','qu','re','ri','ru','sa','se','si','su','ta','te','ti','tu','wa','wo','wu','xi','xu','ya','ye','yi','yo','yu','za','ze','zi','zu'],
        3 => ['ang','bai','ban','bao','bei','ben','bie','bin','cai','can','cao','cen','cha','che','chi','chu','cou','cui','cun','cuo','dai','dan','dao','dei','den','dia','die','diu','dou','dui','dun','duo','eng','fan','fei','fen','fou','gai','gan','gao','gei','gen','gou','gua','gui','gun','guo','hai','han','hao','hei','hen','hng','hou','hua','hui','hun','huo','jia','jie','jin','jiu','jue','jun','kai','kan','kao','kei','ken','kou','kua','kui','kun','kuo','lai','lan','lao','lei','lia','lie','lin','liu','lou','lue','lun','luo','mai','man','mao','mei','men','mie','min','miu','mou','nai','nan','nao','nei','nen','nie','nin','niu','nou','nue','nuo','pai','pan','pao','pei','pen','pie','pin','pou','qia','qie','qin','qiu','que','qun','ran','rao','ren','rou','rua','rui','run','ruo','sai','san','sao','sen','sha','she','shi','shu','sou','sui','sun','suo','tai','tan','tao','tie','tou','tui','tun','tuo','wai','wan','wei','wen','xia','xie','xin','xiu','xue','xun','yan','yao','yin','you','yue','yun','zai','zan','zao','zei','zen','zha','zhe','zhi','zhu','zou','zui','zun','zuo'],
        4 => ['bang','beng','bian','biao','bing','cang','ceng','chai','chan','chao','chen','chou','chua','chui','chun','chuo','cong','cuan','dang','deng','dian','diao','ding','dong','duan','fang','feng','gang','geng','gong','guai','guan','hang','heng','hong','huai','huan','jian','jiao','jing','juan','kang','keng','kong','kuai','kuan','lang','leng','lian','liao','ling','long','luan','mang','meng','mian','miao','ming','nang','neng','nian','niao','ning','nong','nuan','pang','peng','pian','piao','ping','qian','qiao','qing','quan','rang','reng','rong','ruan','sang','seng','shai','shan','shao','shei','shen','shou','shua','shui','shun','shuo','song','suan','tang','teng','tian','tiao','ting','tong','tuan','wang','weng','xian','xiao','xing','xuan','yang','ying','yong','yuan','zang','zeng','zhai','zhan','zhao','zhei','zhen','zhou','zhua','zhui','zhun','zhuo','zong','zuan'],
        5 => ['chang','cheng','chong','chuai','chuan','guang','huang','jiang','jiong','kuang','liang','niang','qiang','qiong','shang','sheng','shuai','shuan','xiang','xiong','zhang','zheng','zhong','zhuai','zhuan'],
        6 => ['chuang', 'shuang', 'zhuang'],
    ];
}


/**
 * @function 移除參數(shù)1中右邊包含的參數(shù)2湾碎,并返回剩余的字符,例如strRemoveRightOnce('wahaha', 'ha')奠货,返回waha
 * @param    $string string 被操作字符串
 * @param    $part   string 要被移除的字符串
 * @return   string
 */
function strRemoveRightOnce($str, $part) {
    if (substr($str, -strlen($part)) == $part) {
        return substr($str, 0, - strlen($part));
    }
    return $str;
}


/**
 * @function 獲取字符串存在的拼音數(shù)量介褥,不兼容-符號,從長往短了截取
 * @param    $str    string 字符
 * @param    $result array  函數(shù)返回的結(jié)果
 * @return   array
 */
function pinYinCutLongToShort($str, $result = []) {
    if($str == '') {
        return $result;
    }

    if(($str == '') && ($result == [])) {
        return [];
    }

    //判斷是否是純拼音递惋,不是直接過濾
    if((! preg_match('/^[a-z]+$/', $str)) && ($result == [])) {
        return [];
    }

    $initial_arr = pinYinArr();
    $initial_keys = array_keys($initial_arr);
    $max = max($initial_keys);
    $min = min($initial_keys);
    
    for($i = $max; $i >= $min; $i--) {
        $substring = substr($str,  - $i);
        if(in_array($substring, $initial_arr[$i])) {
            array_unshift($result, $substring);
            //避免xiao ha ha,用ltrim函數(shù)萍虽,一次性移除掉了兩個(gè)ha造成的計(jì)量有誤
            return pinYinCutLongToShort(strRemoveRightOnce($str, $substring), $result);
        } else {
            if($i == $min) {
                return [];
            }
        }
    }

    return $result;
}


print_r(pinYinCutLongToShort('bianchengyuyan'));
Array
(
    [0] => bian
    [1] => cheng
    [2] => yu
    [3] => yan
)

算法調(diào)優(yōu)注意的地方

  • 如果檢測到含有非拼音的字符(例如有數(shù)字)睛廊,以及多余的拼音字符(例如zhangxsan張x三),會(huì)直接返回空數(shù)組杉编。
  • 代碼采用從長往短切割的策略超全,以xianggang(香港)舉例:
    • 從長到短(for循環(huán)遞減):分成xiang、gang邓馒。粒度大嘶朱,但是失敗率小。
    • 從短到長(for循環(huán)遞增):拆分成xi绒净、an见咒,后面的gg沒法切了。粒度更小挂疆,容易出錯(cuò)改览。
    • 從長到短缺點(diǎn)也很明顯:相應(yīng)的會(huì)忽略精度,所以xian(西安)會(huì)記作一個(gè)拼音缤言,當(dāng)做xian(賢)處理宝当。
  • 代碼采用的從字符串右邊往左切的策略,進(jìn)一步避免切割出錯(cuò)胆萧。例如xianguang(閑逛):
    • 從左到右從長到短:xiang庆揩、uang沒辦法切了俐东。
    • 從左到右從短到長:xi、an订晌、gu虏辫、an、g沒辦法切了锈拨。
    • 從右到左從長到短:guang砌庄、xian,剛剛好奕枢。
    • 從右到左從短到長:ang娄昆、gu、an缝彬、xi萌焰,也行。
  • 結(jié)語:從長往短了切割用于減少失敗率谷浅,從右往左切割扒俯,用于進(jìn)一步避免出錯(cuò),因此被采用壳贪。
  • 注意:以上算法陵珍,并非適合所有場景,可能存在誤差违施,畢竟沒有NLP的AI算法加持(自然語言處理)互纯。
  • 補(bǔ)充:若讀者想要獲取最細(xì)粒度的拼音,不必再原有函數(shù)上改動(dòng)磕蒲,可以將返回的數(shù)組結(jié)果遍歷留潦,再次調(diào)用另一個(gè)切割函數(shù)(注意另一個(gè)函數(shù)是從短到長切割),隨后匯總辣往。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末兔院,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子站削,更是在濱河造成了極大的恐慌坊萝,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件许起,死亡現(xiàn)場離奇詭異十偶,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)园细,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門惦积,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人猛频,你說我怎么就攤上這事狮崩≈朊悖” “怎么了?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵睦柴,是天一觀的道長诽凌。 經(jīng)常有香客問我,道長坦敌,這世上最難降的妖魔是什么皿淋? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮恬试,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘疯暑。我一直安慰自己训柴,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布妇拯。 她就那樣靜靜地躺著幻馁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪越锈。 梳的紋絲不亂的頭發(fā)上仗嗦,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音甘凭,去河邊找鬼稀拐。 笑死,一個(gè)胖子當(dāng)著我的面吹牛丹弱,可吹牛的內(nèi)容都是我干的德撬。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼躲胳,長吁一口氣:“原來是場噩夢啊……” “哼蜓洪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坯苹,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤隆檀,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后粹湃,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恐仑,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年再芋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了菊霜。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡济赎,死狀恐怖鉴逞,靈堂內(nèi)的尸體忽然破棺而出记某,到底是詐尸還是另有隱情,我是刑警寧澤构捡,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布液南,位于F島的核電站,受9級特大地震影響勾徽,放射性物質(zhì)發(fā)生泄漏滑凉。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一喘帚、第九天 我趴在偏房一處隱蔽的房頂上張望畅姊。 院中可真熱鬧,春花似錦吹由、人聲如沸若未。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽粗合。三九已至,卻和暖如春乌昔,著一層夾襖步出監(jiān)牢的瞬間隙疚,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工磕道, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留供屉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓溺蕉,卻偏偏與公主長得像贯卦,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子焙贷,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

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