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生成随机密码
Mar 10 Python
深入理解Python中命名空间的查找规则LEGB
Aug 06 Python
一键搞定python连接mysql驱动有关问题(windows版本)
Apr 23 Python
python字典键值对的添加和遍历方法
Sep 11 Python
Python常见异常分类与处理方法
Jun 04 Python
numpy的文件存储.npy .npz 文件详解
Jul 09 Python
python中多个装饰器的执行顺序详解
Oct 08 Python
对pyqt5之menu和action的使用详解
Jun 20 Python
python3使用Pillow、tesseract-ocr与pytesseract模块的图片识别的方法
Feb 26 Python
在django中实现choices字段获取对应字段值
Jul 12 Python
python日志通过不同的等级打印不同的颜色(示例代码)
Jan 13 Python
解决pytorch 的state_dict()拷贝问题
Mar 03 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
php实现给图片加灰色半透明效果的方法
2014/10/20 PHP
php的优点总结 php有哪些优点
2019/07/19 PHP
javascript replace()正则替换实现代码
2010/02/26 Javascript
jQuery aminate方法定位到页面具体位置
2013/12/26 Javascript
Vuex2.0+Vue2.0构建备忘录应用实践
2016/11/30 Javascript
JavaScript实现时钟滴答声效果
2017/01/29 Javascript
vue之数据交互实例代码
2017/06/16 Javascript
浅谈vue自定义全局组件并通过全局方法 Vue.use() 使用该组件
2017/12/07 Javascript
实例详解Node.js 函数
2018/06/10 Javascript
nodejs基础之buffer缓冲区用法分析
2018/12/26 NodeJs
js实现京东秒杀倒计时功能
2019/01/21 Javascript
详解js中let与var声明变量的区别
2020/04/05 Javascript
浅谈vue获得后台数据无法显示到table上面的坑
2020/08/13 Javascript
[01:11:11]Alliance vs RNG 2019国际邀请赛淘汰赛 败者组BO1 8.20.mp4
2020/07/19 DOTA
python操作CouchDB的方法
2014/10/08 Python
python中字符串比较使用is、==和cmp()总结
2018/03/18 Python
对python3 中方法各种参数和返回值详解
2018/12/15 Python
Python 统计位数为偶数的数字代码详解
2020/03/15 Python
python Canny边缘检测算法的实现
2020/04/24 Python
轻松制作精彩视频:Animoto
2018/09/19 全球购物
世界上最大的在线汽车租赁预订平台:Rentalcars.com(支持中文)
2018/10/12 全球购物
巴黎欧莱雅法国官网:L’Oreal Paris
2019/04/30 全球购物
新浪微博实习心得体会
2014/01/27 职场文书
英语专业职业生涯规划范文
2014/03/05 职场文书
经理秘书求职自荐信范文
2014/03/23 职场文书
专业技术职务聘任书
2014/03/29 职场文书
小学三年级学生评语
2014/04/22 职场文书
节能环保家庭事迹材料
2014/08/27 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
中国梦宣传标语口号
2015/12/26 职场文书
简单介绍 http请求响应参数、无连接无状态、MIME、状态码、端口、telnet、curl
2021/03/31 HTML / CSS
python 爬取吉首大学网站成绩单
2021/06/02 Python
JavaScript中MutationObServer监听DOM元素详情
2021/11/27 Javascript
Redis中有序集合的内部实现方式的详细介绍
2022/03/16 Redis
Python中的matplotlib绘制百分比堆叠柱状图,并为每一个类别设置不同的填充图案
2022/04/20 Python
Vue3实现简易音乐播放器组件
2022/08/14 Vue.js