如何用 Python 判断一个字符串里出现了多少个汉字

请教一种最简洁的实现方式,谢谢各位。
如何用 Python 判断一个字符串里出现了多少个汉字

17 回复

len(re.findall(ur’[\u4e00-\u9fff]’, sample)

不过我感觉在文本处理的技术层面,所谓“汉字”应该是没有准确定义的


import re

def count_chinese_characters(text):
    """
    统计字符串中汉字的数量
    
    参数:
        text: 要统计的字符串
        
    返回:
        汉字数量
    """
    # 使用正则表达式匹配汉字
    # \u4e00-\u9fff 是汉字在Unicode中的基本范围
    # \u3400-\u4dbf 是扩展A区汉字
    # \u20000-\u2A6DF 是扩展B区汉字(需要代理对处理)
    pattern = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf]')
    matches = pattern.findall(text)
    return len(matches)

# 测试示例
if __name__ == "__main__":
    # 测试用例
    test_strings = [
        "Hello World",  # 无汉字
        "你好世界",      # 纯汉字
        "Hello 你好 World",  # 混合
        "Python编程很有趣",  # 混合
        "123abc你好",  # 数字字母汉字混合
        "𠮷𠮷𠮷",  # 扩展B区汉字(需要代理对)
    ]
    
    for text in test_strings:
        count = count_chinese_characters(text)
        print(f"字符串: '{text}'")
        print(f"汉字数量: {count}")
        print("-" * 30)

这个函数的核心是使用正则表达式匹配汉字字符。主要注意点:

  1. Unicode范围

    • \u4e00-\u9fff:基本汉字区(20992个字符)
    • \u3400-\u4dbf:扩展A区(6582个字符)
  2. 扩展B区处理: 对于扩展B区汉字(如"𠮷"),上面的正则表达式可能无法完全匹配。如果需要支持所有汉字,包括扩展B区,可以使用更全面的正则表达式:

    pattern = re.compile(r'[\u4e00-\u9fff\u3400-\u4dbf\U00020000-\U0002A6DF]', re.UNICODE)
    

    注意:扩展B区使用\U00020000-\U0002A6DF表示,且需要re.UNICODE标志。

  3. 代理对问题: 扩展B区汉字在Python字符串中通常以代理对形式存在,正则表达式可以正确处理。

  4. 性能考虑: 对于大量文本处理,预编译正则表达式(如示例所示)可以提高性能。

  5. 边界情况

    • 空字符串:返回0
    • 纯英文/数字:返回0
    • 混合内容:只统计汉字部分

一句话建议:用正则匹配Unicode汉字范围最直接。

如果要区分日语、俄语等各国语言就比较麻烦了

正则[\u4e00-\u9fa5]+

上面提供的 unicode 编码范围应该不完全,比如“㗊”这个字,它是不是汉字?

import jieba

俄语里也会有汉字?

<br><br>class Char(object):<br> widths = [<br> (126, 1), (159, 0), (687, 1), (710, 0), (711, 1),<br> (727, 0), (733, 1), (879, 0), (1154, 1), (1161, 0),<br> (4347, 1), (4447, 2), (7467, 1), (7521, 0), (8369, 1),<br> (8426, 0), (9000, 1), (9002, 2), (11021, 1), (12350, 2),<br> (12351, 1), (12438, 2), (12442, 0), (19893, 2), (19967, 1),<br> (55203, 2), (63743, 1), (64106, 2), (65039, 1), (65059, 0),<br> (65131, 2), (65279, 1), (65376, 2), (65500, 1), (65510, 2),<br> (120831, 1), (262141, 2), (1114109, 1),<br> ]<br><br> <br> def get_char_width(cls, o):<br> o = ord(o)<br> if o == 0xe or o == 0xf:<br> return 0<br> for num, wid in cls.widths:<br> if o &lt;= num:<br> return wid<br> return 1<br><br> <br> def get_string_width(cls, string):<br> # 显示文字的宽度<br> return sum(map(cls.get_char_width, string))<br><br>

简单除暴实现,假设文本只包含 ASCII 字符和中文

In [50]: bs
Out[50]: b’>\xe5\xa6\x82\xe4\xbd\x95\xe7\x94\xa8 Python \xe5\x88\xa4\xe6\x96\xad\xe4\xb8\x80\xe4\xb8\xaa\xe5\xad\x97\xe7\xac\xa6\xe4\xb8\xb2\xe9\x87\x8c\xe5\x87\xba\xe7\x8e\xb0\xe4\xba\x86\xe5\xa4\x9a\xe5\xb0\x91\xe4\xb8\xaa\xe6\xb1\x89\xe5\xad\x97 - V2EX’

In [51]: s = bs.decode()

In [52]: s
Out[52]: '>如何用 Python 判断一个字符串里出现了多少个汉字 - V2EX’

In [53]: [i for i in s if ord(i) not in range(0x20, 0x7f)]
Out[53]:
[‘如’,
‘何’,
‘用’,
‘判’,
‘断’,
‘一’,
‘个’,
‘字’,
‘符’,
‘串’,
‘里’,
‘出’,
‘现’,
‘了’,
‘多’,
‘少’,
‘个’,
‘汉’,
‘字’]

接上条,\r 和 \n 也算进去了,用 0x00 替换 0x20

用正则去搜索 unicode 编码表应该是最优方案了

!pip install zhon
import re
import zhon
len(re.findall(’[{}]’.format(zhon.hanzi.characters),“中文”))

2E80 ~ 33FFh:中日韩符号区。收容康熙字典部首、中日韩辅助部首、注音符号、日本假名、韩文音符,中日韩的符号、标点、带圈或带括符文数字、月份,以及日本的假名组合、单位、年号、月份、日期、时间等。
3400 ~ 4DFFh:中日韩认同表意文字扩充 A 区,总计收容 6,582 个中日韩汉字。
4E00 ~ 9FFFh:中日韩认同表意文字区,总计收容 20,902 个中日韩汉字。
A000 ~ A4FFh:彝族文字区,收容中国南方彝族文字和字根。
AC00 ~ D7FFh:韩文拼音组合字区,收容以韩文音符拼成的文字。
F900 ~ FAFFh:中日韩兼容表意文字区,总计收容 302 个中日韩汉字。
FB00 ~ FFFDh:文字表现形式区,收容组合拉丁文字、希伯来文、阿拉伯文、中日韩直式标点、小符号、半角符号、全角符号等。

面试算法题既视感。。。逃~~

回到顶部