应优先使用 Counter.most_common(10) 获取词频 Top10,因其基于 heapq.nlargest,时间复杂度 O(n + k log n),优于 sorted 全排序的 O(n log n);需预处理文本(小写、正则分词、去停用词),中文须先用 jieba 等工具分词再计数。

直接用 Counter.most_common(10),别手写排序或遍历——这是最简、最快、最不易出错的方式。
为什么不用 sorted() 手动排序?
很多人看到“Top10”第一反应是 sorted(counter.items(), key=lambda x: x[1], reverse=True)[:10]。这能跑通,但多做了三件事:把所有键值对转成列表、全量排序、再切片。而 Counter.most_common(n) 内部用的是堆(heapq.nlargest),时间复杂度是 O(n + k log n)(k=10),远优于全排序的 O(n log n),尤其当总词数几十万时,差距明显。
常见错误现象:sorted(...)[:10] 在处理百万级词汇时卡顿明显,且内存占用高;而 most_common(10) 响应几乎无感。
- 只要目标是固定 TopK(比如 Top10),无条件优先选
most_common(k) - 如果后续还要按字母序排同频词,再对结果二次处理,别混在第一步里做
-
most_common()返回的是list[tuple[str, int]],不是 dict,注意类型
Counter 初始化前要不要预处理文本?
要。原始文本里混着标点、大小写、空格、换行符,直接 Counter(text.split()) 会把 "Python" 和 "python" 当不同词,"word." 和 "word" 也分开计。这不是 Counter 的问题,是输入脏。
立即学习“Python免费学习笔记(深入)”;
典型使用场景:分析英文日志、评论、爬取的网页正文。推荐预处理链:
- 转小写:
text.lower() - 用正则提取纯字母/数字词:
re.findall(r'\b[a-zA-Z]+\b', text)(跳过数字可改[a-zA-Z]) - 过滤停用词(如需)放在
Counter之后更高效:[(w,c) for w,c in counter.most_common(10) if w not in stop_words]
别在 Counter 构造时传巨大字符串——先分词再计数,否则 Counter('hello world') 会统计每个字符,不是每个词。
遇到中文怎么办?Counter 本身不支持分词
Counter 只认 Python 对象,它不管语义。中文没空格分隔,text.split() 没用,直接喂给 Counter 会按字统计(比如“你好世界”→ {'你':1, '好':1, '世':1, '界':1}),不是你要的词频。
必须先用分词工具切出词,再喂给 Counter:
- 轻量场景用
jieba:words = jieba.lcut(text),再Counter(words).most_common(10) - 注意
jieba.lcut默认模式可能切出大量单字,加jieba.cut_for_search(text)或自定义词典提升准确率 - 别用
Counter(text)处理中文原文——那是字频,不是词频
性能影响:jieba 分词比英文正则慢一个数量级,但只做一次;Counter 计数本身仍是毫秒级,瓶颈永远在分词,不在 most_common。
真正容易被忽略的是:Top10 结果里高频词常含无意义符号(如 ''、' '、'\n'),这说明预处理漏了 strip 或正则没写对;还有人把 most_common() 误写成 most_commons(),报 AttributeError——函数名少个 s,但错误信息不提示拼写,得自己盯紧。


















