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


Posted in Python onMay 09, 2017

本文实例讲述了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、笔画数 部首,以及笔顺编号(拼音部分没有音调,而且个别注音有误,如 ?郑?g,??茸郑?褂眯枳⒁狻#┪姨崛×似渲械谋仕呈?荩?钟媒?炯?摹笆涤煤鹤肿?匆簟背绦蛑谱髁?nicode汉字音调版,其中中文汉字用四声标注,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')

终于得到了“李钱佘孙赵”,示例文件点此下载

这里我没有考虑多音字的情况。如果想让程序自动识别,可以增加多音词组对照表,通过上下文来判断。我不知道哪里有这样的数据,反正对于多音字不太多的情形,手动调整也就够了。

Python 相关文章推荐
python实现划词翻译
Apr 23 Python
简洁的十分钟Python入门教程
Apr 03 Python
Python算法输出1-9数组形成的结果为100的所有运算式
Nov 03 Python
pandas中Timestamp类用法详解
Dec 11 Python
python 对象和json互相转换方法
Mar 22 Python
python获取程序执行文件路径的方法(推荐)
Apr 26 Python
Python创建普通菜单示例【基于win32ui模块】
May 09 Python
python-Web-flask-视图内容和模板知识点西宁街
Aug 23 Python
Python 随机生成测试数据的模块:faker基本使用方法详解
Apr 09 Python
Python图像处理二值化方法实例汇总
Jul 24 Python
一篇文章搞懂python混乱的切换操作与优雅的推导式
Aug 23 Python
详解pytorch创建tensor函数
Mar 22 Python
浅谈python socket函数中,send与sendall的区别与使用方法
May 09 #Python
Python利用operator模块实现对象的多级排序详解
May 09 #Python
网站渗透常用Python小脚本查询同ip网站
May 08 #Python
Python获取当前路径实现代码
May 08 #Python
Django自定义分页与bootstrap分页结合
Feb 22 #Python
利用python写个下载teahour音频的小脚本
May 08 #Python
通过源码分析Python中的切片赋值
May 08 #Python
You might like
一个可查询所有表的“通用”查询分页类
2006/10/09 PHP
第三节--定义一个类
2006/11/16 PHP
php中echo()和print()、require()和include()等易混淆函数的区别
2012/02/22 PHP
正确的PHP匹配UTF-8中文的正则表达式
2015/05/13 PHP
整理8个很棒的 jQuery 倒计时插件和教程
2011/12/12 Javascript
A标签触发onclick事件而不跳转的多种解决方法
2013/06/27 Javascript
js获取判断上传文件后缀名的示例代码
2014/02/19 Javascript
纯js实现重发验证码按钮倒数功能
2015/04/21 Javascript
jQuery Dialog对话框事件用法实例分析
2016/05/10 Javascript
零基础轻松学JavaScript闭包
2016/12/30 Javascript
angularjs点击图片放大实现上传图片预览
2017/02/24 Javascript
node.js 抓取代理ip实例代码
2017/04/30 Javascript
JavaScript之生成器_动力节点Java学院整理
2017/06/30 Javascript
JS 60秒后重新发送验证码的实例讲解
2017/07/26 Javascript
Vue-resource拦截器判断token失效跳转的实例
2017/10/27 Javascript
JS获取浏览器地址栏的多个参数值的任意值实例代码
2018/07/24 Javascript
微信小程序中使用自定义图标(阿里icon)的方法
2018/08/20 Javascript
vue实现在一个方法执行完后执行另一个方法的示例
2018/08/25 Javascript
JS获取当前时间的实例代码(昨天、今天、明天)
2018/11/13 Javascript
vue+springboot+element+vue-resource实现文件上传教程
2020/10/21 Javascript
Vue 401配合Vuex防止多次弹框的案例
2020/11/11 Javascript
如何利用nodejs自动定时发送邮件提醒(超实用)
2020/12/01 NodeJs
[02:51]2014DOTA2 TI小组赛总结中国军团全部进军钥匙球馆
2014/07/15 DOTA
python套接字流重定向实例汇总
2016/03/03 Python
微信 用脚本查看是否被微信好友删除
2016/10/28 Python
python3使用SMTP发送HTML格式邮件
2018/06/19 Python
python调用staf自动化框架的方法
2018/12/26 Python
如何基于python实现脚本加密
2019/12/28 Python
Pycharm添加虚拟解释器报错问题解决方案
2020/10/13 Python
html5/css3响应式页面开发总结
2018/10/16 HTML / CSS
美国山地自行车、露营、户外装备和服装购物网站:Aventuron
2018/05/05 全球购物
课前三分钟演讲稿
2014/04/24 职场文书
大学生见习期满自我鉴定
2014/09/13 职场文书
大学生村官个人对照检查材料(群众路线)
2014/09/26 职场文书
考试作弊万能检讨书
2014/10/19 职场文书
台式电脑蓝牙适配器怎么安装?台式电脑蓝牙适配器安装教程
2022/04/08 数码科技