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')

输出是:"佘孙李赵钱";而保存成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正则表达式用法总结》、《Python数据结构与算法教程》、《Python Socket编程技巧总结》、《Python函数使用技巧总结》、《Python字符串操作技巧汇总》、《Python入门与进阶经典教程》及《Python文件与目录操作技巧汇总》

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

(0)

相关推荐

  • python sort、sorted高级排序技巧

    Python list内置sort()方法用来排序,也可以用python内置的全局sorted()方法来对可迭代的序列排序生成新的序列. 1)排序基础 简单的升序排序是非常容易的.只需要调用sorted()方法.它返回一个新的list,新的list的元素基于小于运算符(__lt__)来排序. 复制代码 代码如下: >>> sorted([5, 2, 3, 1, 4]) [1, 2, 3, 4, 5] 你也可以使用list.sort()方法来排序,此时list本身将被修改.通常此方法不如s

  • python实现忽略大小写对字符串列表排序的方法

    本文实例讲述了python实现忽略大小写对字符串列表排序的方法,是非常实用的技巧.分享给大家供大家参考.具体分析如下: 先来看看如下代码: string = ''' the stirng Has many line In THE fIle jb51 net ''' list_of_string = string.split() print list_of_string #将字符串分离开,放入列表中 print '*'*50 def case_insensitive_sort(liststring

  • Python对两个有序列表进行合并和排序的例子

    假设有2个有序列表l1.l2,如何效率比较高的将2个list合并并保持有序状态,这里默认排序是正序. 思路是比较简单的,无非是依次比较l1和l2头部第一个元素,将比较小的放在一个新的列表中,以此类推,直到所有的元素都被放到新的列表中. 考虑2个列表l1 = [2], l2 = [1],如何将他们合并呢?(注意:下面实现会改变l1和l2本来的值) 复制代码 代码如下: def signle_merge_sort(l1, l2):    tmp = []    if l1[0] < l2[0]:  

  • python 实现插入排序算法

    复制代码 代码如下: #!/usr/bin/python def insert_sort(array): for i in range(1, len(array)): key = array[i] j = i - 1 while j >= 0 and key < array[j]: array[j + 1] = array[j] j-=1 array[j + 1] = key if __name__ == "__main__": array = [2, 4, 32, 64,

  • Python中字典(dict)和列表(list)的排序方法实例

    一.对列表(list)进行排序 推荐的排序方式是使用内建的sort()方法,速度最快而且属于稳定排序 复制代码 代码如下: >>> a = [1,9,3,7,2,0,5]>>> a.sort()>>> print a[0, 1, 2, 3, 5, 7, 9]>>> a.sort(reverse=True)>>> print a[9, 7, 5, 3, 2, 1, 0]>>> b = ['e','a'

  • python快速排序代码实例

    一. 算法描述: 1.先从数列中取出一个数作为基准数.2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边.3.再对左右区间重复第二步,直到各区间只有一个数.  二.python快速排序代码 复制代码 代码如下: #!/usr/bin/python# -*- coding: utf-8 -*- def sub_sort(array,low,high):    key = array[low]    while low < high:        while low <

  • Python中对列表排序实例

    很多时候,我们需要对List进行排序,Python提供了两个方法,对给定的List L进行排序: 方法1.用List的成员函数sort进行排序 方法2.用built-in函数sorted进行排序(从2.4开始) 这两种方法使用起来差不多,以第一种为例进行讲解: 从Python2.4开始,sort方法有了三个可选的参数,Python Library Reference里是这样描述的 复制代码 代码如下: cmp:cmp specifies a custom comparison function

  • python冒泡排序算法的实现代码

    1.算法描述:(1)共循环 n-1 次(2)每次循环中,如果 前面的数大于后面的数,就交换(3)设置一个标签,如果上次没有交换,就说明这个是已经好了的. 2.python冒泡排序代码 复制代码 代码如下: #!/usr/bin/python# -*- coding: utf-8 -*- def bubble(l):    flag = True    for i in range(len(l)-1, 0, -1):        if flag:             flag = False

  • python选择排序算法的实现代码

    1.算法:对于一组关键字{K1,K2,-,Kn}, 首先从K1,K2,-,Kn中选择最小值,假如它是 Kz,则将Kz与 K1对换:然后从K2,K3,- ,Kn中选择最小值 Kz,再将Kz与K2对换.如此进行选择和调换n-2趟,第(n-1)趟,从Kn-1.Kn中选择最小值 Kz将Kz与Kn-1对换,最后剩下的就是该序列中的最大值,一个由小到大的有序序列就这样形成. 2.python 选择排序代码: 复制代码 代码如下: def selection_sort(list2):    for i in

  • python实现的各种排序算法代码

    复制代码 代码如下: # -*- coding: utf-8 -*-# 测试各种排序算法# link:www.jb51.net# date:2013/2/2 #选择排序def select_sort(sort_array):    for i, elem in enumerate(sort_array):        for j, elem in enumerate(sort_array[i:]):            if sort_array[i] > sort_array[j + i]

随机推荐