Python实现中文正确排序的方法与代码示例
本文详细解析Python中中文排序的难点,指出GB2312与Unicode编码导致的排序混乱问题。通过构建包含拼音、笔画及笔顺的字典,实现符合新华字典规范的中文排序。提供完整的Python代码示例,支持按拼音四声及笔画顺序排列汉字,解决多音字外的常规排序需求。
本文介绍一种在Python中实现中文正确排序的方法,供读者参考。
Python在比较字符串大小时,依据的是ord函数返回的编码值。利用这一特性,sort函数可以轻松地按顺序排列数字和英文字母,因为它们在编码表中本身就是有序的。
>> print ','< '1'<'A'<'a'<'阿' True
然而,处理中文排序则复杂得多。中文排序通常涉及拼音和笔画两种方式。在常用的GB2312标准字符集中,3755个一级汉字按拼音顺序编码,而3008个二级汉字则按部首笔画排列。
>> print '曙'< '鲑','曾'<'怡' True True
这种编码方式导致排序结果出现偏差。例如,‘曙’和‘曾’属于常用字,而‘鲑’和‘怡’属于次常用字。尽管从拼音或笔画角度,这两对字的顺序应当相反,但由于GBK和GB18030编码为了向下兼容未修改原有顺序,导致sort排序后的结果混乱。
另一方面,Unicode编码中的中文是按照《康熙字典》的偏旁部首和笔画数进行排列的,因此其排序结果与GB编码的结果存在差异。
# encoding=utf8
char=['赵','钱','孙','李','佘']
char.sort()
for item in char:
print item.decode('utf-8').encode('gb2312')
若将字符列表['赵','钱','孙','李','佘']进行排序并输出UTF-8字符串,结果为:"佘孙李赵钱";若保存为GB2312编码后
# encoding=gb2312 char=['赵','钱','孙','李','佘'] char.sort() for item in char: print item
输出结果变为:“李钱孙赵佘”。显然,这两种结果均不符合常规的中文排序习惯。那么,如何实现对中文的正确排序呢?
首先需要明确中文词典的排序规则:先按拼音排列,并区分四声;若拼音相同,则比较笔画数目;若笔画数也相同,则按笔顺中的具体笔画类型区分,新华字典采用的顺序是一丨丿丶乙(俗称“天上人间”),通常不会有完全相同的笔划类型。因此,中文排序不仅需要带音调的汉字拼音对照表,还需要具体的笔顺数据。
起初尝试寻找现成模块,但效果不佳。pyzh的转换代码仅支持不到7千字,且缺乏音调信息;水木社区的roy代码涵盖2万多字符,但依赖pysqlite支持。最终决定自行实现。
目前找到的最全面数据是slowwind9999上传至CSDN的Unicode汉字编码表,包含全部20902个汉字的全拼、五笔、郑码、UNICODE、GBK、笔画数、部首及笔顺编号。需注意,拼音部分无音调,且个别字(如囍、猤、啹等)注音有误。笔者提取了其中的笔顺数据,并利用江志键的“实用汉字转拼音”程序制作了Unicode汉字音调版,中文汉字用四声标注,319个日韩汉字无音调以示区别,并根据汉典数据略作修正(仍可能存在少量错误)。基于这两个对照表,后续处理变得简单。
# 建立拼音辞典
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()
笔顺字典的处理方法与拼音字典相同。尽管文本包含两万行,导入速度依然很快,约需0.5秒。若将这两个文件合并统一处理,效率应更高。
# 辞典查找函数
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
查找中文时,一律转换为UTF-8字符串,汉字外的其他字符不做处理,原样输出。如需获取声母,仅输出拼音的第一个字符即可。只要数据准确,比较过程便十分轻松。数字在字母之前,例如“爱”(ai4)会排在“昂”(ang2)之前。笔顺值的位数代表笔画数,数值对应笔画权重,直接比较数字大小即可得到正确顺序。代码如下:
#比较单个字符
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
# 排序函数
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
现在,我们可以按照字典规范对中文进行排序。
char=['赵','钱','孙','李','佘']
char=cnsort(char)
for item in char:
print item.decode('utf-8').encode('gb2312')
最终得到排序结果“李钱佘孙赵”,示例文件可点击此处下载。
本文未考虑多音字情况。若需程序自动识别,可增加多音词组对照表并通过上下文判断。目前缺乏此类数据,对于多音字较少的场景,手动调整即可满足需求。
PS:此处推荐两款实用的在线排序工具供参考:
在线中英文根据首字母排序工具: http://tools.jb51.net/aideddesign/zh_paixu
在线文本倒序翻转排序工具: http://tools.jb51.net/aideddesign/flipped_txt
更多关于Python相关内容可查看本站专题:《Python正则表达式用法总结》、《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》
希望本文所述内容对大家Python程序设计有所帮助。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









