Python實(shí)現(xiàn)針對(duì)中文排序的方法
本文實(shí)例講述了Python實(shí)現(xiàn)針對(duì)中文排序的方法。分享給大家供大家參考,具體如下:
Python比較字符串大小時(shí),根據(jù)的是ord函數(shù)得到的編碼值。基于它的排序函數(shù)sort可以很容易為數(shù)字和英文字母排序,因?yàn)樗鼈冊(cè)诰幋a表中就是順序排列的。
>> print ','< '1'<'A'<'a'<'阿' True
但要很處理中文就沒(méi)那么容易了。中文通常有拼音和筆畫兩種排序方式,在最常用中文標(biāo)準(zhǔn)字符集GB2312中,3755個(gè)一級(jí)中文漢字是按照拼音序進(jìn)行編碼的,而3008個(gè)二級(jí)漢字則是按部首筆畫排列,
>> print '曙'< '鮭','曾'<'怡' True True
出現(xiàn)這樣的結(jié)果是因?yàn)椤?和‘曾'都是常用字,而‘鮭'和‘怡'都是次常用字,但無(wú)論從筆畫還是拼音來(lái)看,這兩對(duì)順序都應(yīng)該反過(guò)來(lái)。后來(lái)擴(kuò)充的GBK和GB18030編碼為了向下兼容,都沒(méi)有更改之前的漢字順序,于是sort之后的次序就很亂了。
另一方面unicode編碼的中文是按《康熙字典》的偏旁部首和筆畫數(shù)來(lái)排列的,所以排序結(jié)果和GB編碼又不一樣。
# encoding=utf8 char=['趙','錢','孫','李','佘'] char.sort() for item in char: print item.decode('utf-8').encode('gb2312')
輸出是:"佘孫李趙錢";而保存成gb2312編碼后
# encoding=gb2312 char=['趙','錢','孫','李','佘'] char.sort() for item in char: print item
輸出是:“李錢孫趙佘”。顯然,這兩個(gè)結(jié)果都不是我們想要的。那我們究竟怎樣才能對(duì)中文正確排序呢?
先要弄清楚中文詞典的排序規(guī)則:先按拼音排列,區(qū)分四聲,拼音相同的就看筆畫數(shù)目多少,筆畫數(shù)也相同的再按筆順中的具體筆劃類型來(lái)區(qū)分,新華字典采用的順序是一丨丿丶乙,也稱作“天上人間”,應(yīng)該沒(méi)有筆劃類型也完全一樣的。所以中文排序不僅需要帶音調(diào)的漢字拼音對(duì)照表,還需要有具體筆順的數(shù)據(jù)。
本以為有現(xiàn)成的模塊,試了幾個(gè)都不理想。pyzh的轉(zhuǎn)換代碼只支持不到7千字,而且還沒(méi)有音調(diào)。水木的roy的代碼涵蓋了2萬(wàn)多字符,但需要pysqlite支持......還是自立更生吧~
我找到最全的數(shù)據(jù)是slowwind9999上傳到csdn的unicode漢字編碼表(點(diǎn)擊此處本站下載。),包括全部20902個(gè)漢字的全拼、五筆、鄭碼、UNICODE、GBK、筆畫數(shù) 部首,以及筆順編號(hào)(拼音部分沒(méi)有音調(diào),而且個(gè)別注音有誤,如 囍,猤,啹等字,使用需注意。)我提取了其中的筆順數(shù)據(jù),又用江志鍵的“實(shí)用漢字轉(zhuǎn)拼音”程序制作了unicode漢字音調(diào)版,其中中文漢字用四聲標(biāo)注,319個(gè)日韓漢字沒(méi)有音調(diào)以示區(qū)別,并根據(jù)漢典的數(shù)據(jù)略作修正(但仍可能存在錯(cuò)誤)。有了這兩個(gè)對(duì)照表,下面的工作就簡(jiǎn)單了。
# 建立拼音辭典 dic_py = dict() f_py = open('py.txt','r') content_py = f_py.read() lines_py = content_py.split('\n') n=len(lines_py) for i in range(0,n-1): word_py, mean_py = lines_py[i].split('\t', 1) dic_py[word_py]=mean_py f_py.close()
筆順字典的處理方法也完全相同,雖然文本有兩萬(wàn)行,導(dǎo)入還是很快的,0.5秒左右。如果把這兩個(gè)文件合并起來(lái)統(tǒng)一處理,應(yīng)該可以更快。
# 辭典查找函數(shù) def searchdict(dic,uchar): if isinstance(uchar, str): uchar = unicode(uchar,'utf-8') if uchar >= u'\u4e00' and uchar < = u'\u9fa5': value=dic.get(uchar.encode('utf-8')) if value == None: value = '*' else: value = uchar return value
查找中文,一律轉(zhuǎn)為UTF8字符串,漢字外的其他字符不做處理,原樣輸出。如果需要聲母,只輸出拼音的第一個(gè)字符就是了。只要資料準(zhǔn)確,比較起來(lái)就很輕松了。數(shù)字在字母之前,愛(ài)(ai4)便會(huì)比昂(ang2)靠前,而筆順值的位數(shù)代表了筆畫數(shù),數(shù)值對(duì)應(yīng)筆劃?rùn)?quán)重,直接比較數(shù)字大小就可以得到正確的順序。代碼如下:
#比較單個(gè)字符 def comp_char_PY(A,B): if A==B: return -1 pyA=searchdict(dic_py,A) pyB=searchdict(dic_py,B) if pyA > pyB: return 1 elif pyA < pyB: return 0 else: bhA=eval(searchdict(dic_bh,A)) bhB=eval(searchdict(dic_bh,B)) if bhA > bhB: return 1 elif bhA < bhB: return 0 else: return 'Are you kidding?' #比較字符串 def comp_char(A,B): charA = A.decode('utf-8') charB = B.decode('utf-8') n=min(len(charA),len(charB)) i=0 while i < n: dd=comp_char_PY(charA[i],charB[i]) if dd == -1: i=i+1 if i==n: dd=len(charA)>len(charB) else: break return dd # 排序函數(shù) def cnsort(nline): n = len(nline) lines='\n'.join(nline) for i in range(1, n): #插入法 tmp = nline[i] j = i while j > 0 and comp_char(nline[j-1],tmp): nline[j] = nline[j-1] j -= 1 nline[j] = tmp return nline
現(xiàn)在我們就可以按照字典的規(guī)范給中文排序了。
char=['趙','錢','孫','李','佘'] char=cnsort(char) for item in char: print item.decode('utf-8').encode('gb2312')
終于得到了“李錢佘孫趙”,示例文件點(diǎn)此下載。
這里我沒(méi)有考慮多音字的情況。如果想讓程序自動(dòng)識(shí)別,可以增加多音詞組對(duì)照表,通過(guò)上下文來(lái)判斷。我不知道哪里有這樣的數(shù)據(jù),反正對(duì)于多音字不太多的情形,手動(dòng)調(diào)整也就夠了。
PS:這里再為大家推薦2款比較實(shí)用的相關(guān)在線排序工具供大家參考使用:
在線中英文根據(jù)首字母排序工具:
http://tools.jb51.net/aideddesign/zh_paixu
在線文本倒序翻轉(zhuǎn)排序工具:
http://tools.jb51.net/aideddesign/flipped_txt
更多關(guān)于Python相關(guān)內(nèi)容可查看本站專題:《Python正則表達(dá)式用法總結(jié)》、《Python數(shù)據(jù)結(jié)構(gòu)與算法教程》、《Python Socket編程技巧總結(jié)》、《Python函數(shù)使用技巧總結(jié)》、《Python字符串操作技巧匯總》、《Python入門與進(jìn)階經(jīng)典教程》及《Python文件與目錄操作技巧匯總》
希望本文所述對(duì)大家Python程序設(shè)計(jì)有所幫助。
相關(guān)文章
pycharm在調(diào)試python時(shí)執(zhí)行其他語(yǔ)句的方法
今天小編就為大家分享一篇pycharm在調(diào)試python時(shí)執(zhí)行其他語(yǔ)句的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-11-11Django 后臺(tái)獲取文件列表 InMemoryUploadedFile的例子
今天小編就為大家分享一篇Django 后臺(tái)獲取文件列表 InMemoryUploadedFile的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-08-08Python實(shí)現(xiàn)的排列組合、破解密碼算法示例
這篇文章主要介紹了Python實(shí)現(xiàn)的排列組合、破解密碼算法,結(jié)合實(shí)例形式分析了Python排列組合、密碼破解相關(guān)數(shù)學(xué)運(yùn)算操作技巧,需要的朋友可以參考下2019-04-04numpy數(shù)組的重塑和轉(zhuǎn)置實(shí)現(xiàn)
本文主要介紹了numpy數(shù)組的重塑和轉(zhuǎn)置實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-03-03Python實(shí)現(xiàn)的NN神經(jīng)網(wǎng)絡(luò)算法完整示例
這篇文章主要介紹了Python實(shí)現(xiàn)的NN神經(jīng)網(wǎng)絡(luò)算法,結(jié)合完整實(shí)例形式分析了Python使用numpy、matplotlib及sklearn模塊實(shí)現(xiàn)NN神經(jīng)網(wǎng)絡(luò)相關(guān)算法實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2018-06-06Python中super().__init__()測(cè)試以及理解
__init__()一般用來(lái)創(chuàng)建對(duì)象的實(shí)例變量,或一次性操作,super()用于調(diào)用父類的方法,可用來(lái)解決多重繼承問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Python中super().__init__()測(cè)試及理解的相關(guān)資料,需要的朋友可以參考下2021-12-12python使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù)
這篇文章主要介紹了python如何使用ctypes庫(kù)調(diào)用DLL動(dòng)態(tài)鏈接庫(kù),幫助大家更好的理解和使用python,感興趣的朋友可以了解下2020-10-10在django項(xiàng)目中,如何單獨(dú)運(yùn)行某個(gè)python文件
這篇文章主要介紹了在django項(xiàng)目中單獨(dú)運(yùn)行某個(gè)python文件的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04Python快速進(jìn)修指南之向量數(shù)據(jù)庫(kù)文本搜索
這篇文章主要為大家介紹了Java開(kāi)發(fā)快速進(jìn)修Python指南之向量數(shù)據(jù)庫(kù)文本搜索,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01