Python实现针对中文排序的方法

作者:app_ 时间:2022-04-20 23:21:51 

本文实例讲述了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')

输出是:"佘孙李赵钱";而保存成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

查找中文,一律转为UTF8字符串,汉字外的其他字符不做处理,原样输出。如果需要声母,只输出拼音的第一个字符就是了。只要资料准确,比较起来就很轻松了。数字在字母之前,爱(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:这里再为大家推荐2款比较实用的相关在线排序工具供大家参考使用:

在线中英文根据首字母排序工具:
http://tools.jb51.net/aideddesign/zh_paixu

在线文本倒序翻转排序工具:
http://tools.jb51.net/aideddesign/flipped_txt

希望本文所述对大家Python程序设计有所帮助。

标签:Python,中文,排序
0
投稿

猜你喜欢

  • 常用SQL语句词典

    2008-08-03 17:19:00
  • python计算n的阶乘的方法代码

    2023-08-20 07:33:00
  • python实现Dijkstra静态寻路算法

    2021-06-10 07:41:09
  • Python+Pyecharts实现散点图的绘制

    2023-09-02 05:01:29
  • Javascript基础教程之比较操作符

    2024-04-10 16:15:05
  • javascript实现计算器功能详解流程

    2024-04-23 09:27:00
  • sql索引失效的情况以及超详细解决方法

    2024-01-21 09:25:30
  • 低版本Druid连接池+MySQL驱动8.0导致线程阻塞、性能受限

    2024-01-20 05:11:49
  • MySql 备忘录

    2024-01-22 12:56:48
  • Bootstrap风格的WPF样式

    2024-05-02 17:32:17
  • MySQL Left JOIN时指定NULL列返回特定值详解

    2024-01-16 09:55:32
  • python3 requests 各种发送方式详解

    2021-04-06 09:03:22
  • Python如何脚本过滤文件中的注释

    2021-10-03 15:24:52
  • 复化梯形求积分实例——用Python进行数值计算

    2021-10-08 13:03:26
  • jupyter .ipynb转.py的实现操作

    2023-12-15 04:03:11
  • pycharm通过ssh连接远程服务器教程

    2022-10-09 19:44:31
  • Python企业编码生成系统之主程序模块设计详解

    2023-11-18 18:44:37
  • Vue.js 使用v-cloak后仍显示变量的解决方法

    2024-06-07 15:20:56
  • python re.match()用法相关示例

    2023-07-21 05:12:30
  • 详解python实现邮件解析的方法

    2023-02-19 04:03:20
  • asp之家 网络编程 m.aspxhome.com