如何让Python单词计数器将缩约形式计为单个单词?
如何让Python单词计数器正确处理缩约形式(类似Word的计数逻辑)
嘿,这个问题我之前做单词统计工具的时候也踩过坑!原来的正则表达式(比如用\w+)会把can't拆成can和t,完全不符合我们想要的效果。要实现类似Microsoft Word的计数逻辑,核心就是调整正则规则,让它能正确识别带内部撇号的缩约词。
问题根源
默认的\w+正则匹配的是字母、数字和下划线,会把撇号(')当成单词分隔符,所以像don't这类缩约形式会被拆成两个“单词”,直接导致计数错误。
解决方案:定制正则表达式
我们需要写一个正则,既能匹配普通单词,也能匹配包含内部撇号的缩约词(比如can't、I'm、o'clock这类)。推荐使用下面的实现:
import re def count_words(text): # 匹配规则:允许单词内部包含普通撇号或智能撇号 word_pattern = r"\b[a-zA-Z]+(?:['’][a-zA-Z]+)*\b" # 查找所有符合规则的单词,忽略大小写不影响计数结果 matched_words = re.findall(word_pattern, text, re.IGNORECASE) return len(matched_words) # 测试效果 sample_text = "I can't believe you don't know! It's already o'clock, we're running late." print(count_words(sample_text)) # 输出:9(对应单词:I, can't, believe, you, don't, know, It's, o'clock, we're)
正则表达式详解
拆解一下这个正则的核心部分:
\b:单词边界,确保我们匹配的是完整单词,不会把don't里的don单独拆分出来[a-zA-Z]+:匹配一个或多个字母,作为单词的开头主体(?:['’][a-zA-Z]+)*:非捕获组,允许零次或多次出现“撇号(普通或智能撇号)+ 字母”的组合,完美覆盖各种缩约形式re.IGNORECASE:可选参数,让匹配不区分大小写(如果只是计数,这个参数不影响数量;如果要统计词频,可以把匹配到的单词统一转小写)
额外扩展(可选)
如果想让计数器更贴近Word的完整逻辑,还可以补充:
- 处理连字符单词:比如
mother-in-law,可以把正则调整为r"\b[a-zA-Z]+(?:['’-][a-zA-Z]+)*\b",把连字符加入允许的内部符号 - 文本预处理:匹配前先替换多个空格为单个空格,过滤多余的特殊字符
内容的提问来源于stack exchange,提问作者Süleyman Yaman
相关产品推荐
相关产品推荐

