当前位置:   article > 正文

Python实现获取汉字笔画数,根据汉字笔画数量排序_python 计算汉字笔画

python 计算汉字笔画

起因

本人现在所在的公司是由香港人开办的,也是做做香港业务,一个车辆管理系统后台,也包括司机等人员管理。突然有一天,老板说我们的列表找司机不够人性化,不符合用户习惯。因为我们Python对中文排序默认是按照Unicode编码来排序的,很正常嘛,一般都喜欢希望按照拼音来排序。然后我就惊呆了:香港人不会拼音… 那按照五笔排序?也不是,他们要按照汉字的笔画数量排序,笔画少的,排在前面。

额…(靓仔语塞.jpg)

不过既然老板需要,那还是要搞起来的

如果不是做香港业务,我可能永远也不会想到中文排序除了【按照拼音排序】,【按五笔排序】之外,还有什么什么排序。

香港人打字不用拼音,他们用仓颉输入法

实现

思路

首先百度了一大圈,即使强如Python,也没有现成可用的第三方库可用,不过有些思路和代码片段,但是都不怎么完善,需要自己实现。

首先要找一个文件,包含所有汉字,并且有每个汉字对应的笔画数,然后构造成一个字典,字典的键是汉字,值是对应的笔画数。之后计算汉字的笔画数时,就到字典中去取就可以了。

最难找的就是找个汉字对照表文件了,找到了下载还有层层限制,要各种下载币

代码实现

所需用到的字典文件放到gitlab中了,有需要的可自行下载

汉字对照表地址:https://github.com/WuChengqian520/codeSnippet.git

汉字对照表

代码如下:

from typing import Iterable, Callable, Union

# 加载汉字笔画对照文件,参考同级目录下的 chinese_unicode_table.txt 文件格式
chinese_char_map = {}
with open('./chinese_unicode_table.txt', 'r', encoding='UTF-8') as f:
    lines = f.readlines()
    for line in lines[6:]:  # 前6行是表头,去掉
        line_info = line.strip().split()
        # 处理后的数组第一个是文字,第7个是笔画数量
        chinese_char_map[line_info[0]] = line_info[6]


def __sort_by_strokes_core(words: Iterable) -> int:
    """
    统计字符串中所有文字的笔画总数

    :param words: 需要统计的字符串
    :return: 笔画总数
    """
    strokes = 0
    for word in words:
        if 0 <= ord(word) <= 126:  # 数字,英文符号范围
            strokes += 1
        elif 0x4E00 <= ord(word) <= 0x9FA5:  # 常用汉字Unicode编码范围4E00-9FA5,20902个字
            strokes += int(chinese_char_map.get(word, 1))
        else:  # 特殊符号字符一律排在最后
            strokes += 1
    return strokes


def __sort_by_sequence_core(words: Iterable) -> Iterable[int]:
    """
    计算字符串中各个字符的优先级,组成数组返回,用于后面排序,
    优先排数字,再拍英文字母,最后排汉字, 为了确保汉字排在后面,所有汉字在笔画数量基础上再 +1000

    :param words: 需要统计的字符串
    :return: 字符串中字符笔画数列表
    """
    weight = []
    for word in words:
        if 0 <= ord(word) <= 126:  # 数字,英文符号范围
            weight.append(ord(word))
        elif 0x4E00 <= ord(word) <= 0x9FA5:  # 常用汉字Unicode编码范围4E00-9FA5,20902个字
            weight.append(1000 + int(chinese_char_map.get(word, 0)))
        else:  # 特殊符号字符一律排在最后
            weight.append(99999)
    return weight


def sort_by_strokes(object_list: Iterable,
                    model: str = 'sequence',
                    key: Union[Callable, None] = None,
                    reverse=False
                    ) -> Iterable:
    """
    根据笔画数量对中文字符串进行排序

    :param object_list: 文字字符串列表
    :param model: 排序模式,sequence--按照文字笔画依次排序, total--按照笔画总数排序,默认:sequence
    :param key: 文字字符串列表
    :param reverse: 倒序排序
    :return: 排序后的字符串列表

    >>> name_list = ['张三', '李四', '王五', '赵六', '尼古拉丁', '周吴郑王']
    >>> print(sort_by_strokes(name_list))
    ['王五', '尼古拉丁', '张三', '李四', '周吴郑王', '赵六']
    """
    assert model in ['sequence', 'total'], '仅支持【sequence】和【total】两种模式'
    if model == 'sequence':
        _core_function = __sort_by_sequence_core
    else:
        _core_function = __sort_by_strokes_core

    __order_key = '__sort_weight'
    sorted_obj = []
    for obj in object_list:
        words = key(obj) if key else obj
        assert isinstance(words, Iterable), '用于排序的对象必须是一个可迭代对象, 其他类型请自行实现!'
        strokes = _core_function(words)
        # 构建一个新的字典,用于存放排序对象和排序权重,后面根据权重进行排序后再取出对象
        sorted_obj.append({'obj': obj, __order_key: strokes})

    sorted_words = sorted(sorted_obj, key=lambda x: x[__order_key], reverse=reverse)
    # 取出排序后的对象
    sorted_words = [item['obj'] for item in sorted_words]
    return sorted_words


if __name__ == '__main__':
    peoples = ['张三', '李四', '王五', '赵六', '尼古拉丁', '周吴郑王']
    print('普通排序:', sort_by_strokes(peoples))
    print('倒序排序:', sort_by_strokes(peoples, reverse=True))
    print('按照笔画总数排序:', sort_by_strokes(peoples, model='total'))
    students = [
        {'name': '王梓涵', 'sex': '男', 'age': 12, 'grade': 60},
        {'name': '周小静', 'sex': '女', 'age': 13, 'grade': 99},
        {'name': '张靓颖', 'sex': '女', 'age': 11, 'grade': 80},
        {'name': '欧阳晓晓', 'sex': '女', 'age': 14, 'grade': 67},
        {'name': '东方不败', 'sex': '男', 'age': 13, 'grade': 72},
        {'name': '周一天', 'sex': '男', 'age': 15, 'grade': 72},
        {'name': '♂卐', 'sex': '男', 'age': 13, 'grade': 72},
    ]
    print('字典排序:', sort_by_strokes(students, key=lambda x: x['name']))

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104

排序示例:

普通排序: ['王五', '尼古拉丁', '张三', '李四', '周吴郑王', '赵六']
倒序排序: ['赵六', '周吴郑王', '李四', '张三', '尼古拉丁', '王五']
按照笔画总数排序: ['王五', '张三', '李四', '赵六', '尼古拉丁', '周吴郑王']
字典排序: [{'name': '王梓涵', 'sex': '男', 'age': 12, 'grade': 60}, {'name': '东方不败', 'sex': '男', 'age': 13, 'grade': 72}, {'name': '张靓颖', 'sex': '女', 'age': 11, 'grade': 80}, {'name': '周一天', 'sex': '男', 'age': 15, 'grade': 72}, {'name': '周小静', 'sex': '女', 'age': 13, 'grade': 99}, {'name': '欧阳晓晓', 'sex': '女', 'age': 14, 'grade': 67}, {'name': '♂卐', 'sex': '男', 'age': 13, 'grade': 72}]

  • 1
  • 2
  • 3
  • 4
  • 5

最后,打个小广告

欢迎各位访问我的博客:foryou.cool

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/109669
推荐阅读
相关标签
  

闽ICP备14008679号