统计文章中单词出现的次数

      最近看到一本好书《C++ Cookbook》,不是C++语言入门教程,是一本关于c++程序设计日常问题的珍贵解决方案。里面的收集了大量C++比较现实的问题解决方案,如数字计算、日期和时间、字符串和文本操作、多线程和数学编程等等,并且还介绍了Boost库(里面有些问题解决也是用这个库)。里面讲的问题都比较实际,代码实现也很规范,不过也有些问题偏简单,在之前学习语言就知道了。

 

 

 

     举其中的一个例子,如果要统计文章中单词的次数问题,书中是用STL库中的map来实现的,感觉写的比较简洁,自己修改了一下代码如下:

     解决方案

//统计文本文件中每个单词的出现次数

#include <iostream>
#include <map>
#include <string>
#include <fstream>
using namespace std;

typedef map<string,int> StrIntMap;

void CountWords(istream& in, StrIntMap& words)
{
string s;
while(in >> s )
{
   ++words[s];
}
}

int main()
{
ifstream in("in.txt");
StrIntMap w;

CountWords(in, w);

for(StrIntMap::iterator p = w.begin(); p != w.end(); ++p)
{
   cout << p->first << " occured " << p->second << " times." <<endl;
}
   return 0;
}

     问题存在:

      但是这个解决方案也存在问题,就是没对单词进行判断,如文件中有“I love this game.” , 程序运行结果是 “game.” 算一次,单词后面的句号也被当成单词的一部分。后来网上查看了些相关资料,大多是用hash table来实现,但也有些问题出现。
例如符号问题: "Jack's book." 中 的 Jack's 算是单词吗?我觉得Jack 才算?。
例如语法问题(词的变化形式,包括复数、不规则、过去分词、现在分词、比较级和最高级):“It's getting warmer.” 中 It's 算是单词吗? 我觉得是 It 和 is;还有getting 和 warmer 应该算进 原形的 get 和 warm 中呢还是 另外算。
网上很多资料都是不把语法问题考虑进去,而符号问题是把符号当成空格处理(Jack's 就会有 Jack:1次, s: 1次)。不过有个国内软件“英语词频统计2.7”,好像有解决语法问题。

<think> 我们有一个数组,数组中的每个元素是一个句子(字符串)。我们需要统计所有句子中每个单词出现的次数。 根据引用[1][2][3]中的方法,我们可以采用以下步骤: 1. 将数组中的所有句子合并成一个字符串,或者逐个句子处理。 2. 将每个句子拆分成单词(tokenize),并同时处理大小写和标点符号(通常是将所有字母转换为小写,并移除标点)。 3. 使用字典(或Counter)统计每个单词出现的次数。 4. 按出现次数排序。 具体步骤: - 遍历数组中的每个句子。 - 对于每个句子,使用正则表达式或字符串分割来获取单词,同时将单词转换为小写并去除标点。 - 使用字典记录每个单词出现的次数,或者使用collections.Counter。 根据引用[1]中的示例,我们可以使用正则表达式`\w+`来匹配单词(这个正则表达式会匹配字母数字下划线,对于英文单词基本够用,但可能包括数字,如果不需要数字可以调整)。 引用[2]中提到可以使用HashMap(在Python中就是字典)来统计,然后更新词频。 因此,我们可以有两种方法: 方法一:使用collections.Counter(简单快捷) 方法二:使用字典手动统计 我们假设数组名为sentences,由多个句子字符串组成。 方法一示例代码: import re from collections import Counter words = [] for sentence in sentences: words.extend(re.findall(r'\w+', sentence.lower())) # 将句子拆分成单词并转换为小写 word_counts = Counter(words) 方法二:手动使用字典 import re word_counts = {} for sentence in sentences: for word in re.findall(r'\w+', sentence.lower()): word_counts[word] = word_counts.get(word, 0) + 1 然后,我们可以按出现次数排序。Counter对象有一个most_common()方法可以直接得到排序后的列表。如果手动统计,我们可以对字典的项进行排序。 排序示例(针对方法二): sorted_word_counts = sorted(word_counts.items(), key=lambda x: x[1], reverse=True) 注意:引用[3]中提到的问题与我们类似,也是要计算数组中单词的出现次数。 但是,如果数组中的元素不是句子,而是已经拆分好的单词数组,那么我们可以直接统计。但根据问题描述,数组中是句子(句子里有多个单词)。 因此,我们首先需要将句子拆分成单词。 下面给出完整的示例代码(使用方法一): </think> 以下是使用 Python 统计数组中句子内单词出现次数的方法详解,结合引用资料中的最佳实践: ### 方法实现 ```python import re from collections import Counter def count_words(sentences): """ 统计句子数组中单词出现频率 参数: sentences -- 包含句子的字符串数组 返回: 按频率降序排列的 (单词, 次数) 元组列表 """ word_list = [] for sentence in sentences: # 1. 转换为小写 lower_sentence = sentence.lower() # 2. 使用正则提取单词(过滤标点) words = re.findall(r'\b\w+\b', lower_sentence) # \b 匹配单词边界 word_list.extend(words) # 3. 使用Counter统计词频 word_counter = Counter(word_list) # 4. 按频率降序排序 sorted_counts = sorted(word_counter.items(), key=lambda x: x[1], reverse=True) return sorted_counts # 示例用法 if __name__ == "__main__": sentences = [ "Hello world! Python is awesome.", "I love Python programming.", "Python makes data analysis easy." ] result = count_words(sentences) for word, count in result: print(f"{word}: {count}") ``` ### 关键步骤说明 1. **统一大小写** `sentence.lower()` 将所有字母转为小写,避免 "Python" 和 "python" 被识别为不同单词 2. **单词提取** `re.findall(r'\b\w+\b', ...)` 使用正则表达式: - `\b` 匹配单词边界 - `\w+` 匹配一个或多个字母/数字/下划线 - 自动过滤标点符号(如 ! . , 等)[^1][^2] 3. **频率统计** `collections.Counter` 高效统计词频,优于手动循环计数[^2] 4. **结果排序** `sorted(..., key=lambda x: x[1], reverse=True)` 按词频降序排列 ### 输出示例 ``` python: 3 hello: 1 world: 1 is: 1 awesome: 1 i: 1 love: 1 programming: 1 makes: 1 data: 1 analysis: 1 easy: 1 ``` ### 适用场景 1. 文本分析(如文章关键词提取) 2. 日志文件处理(如错误类型统计) 3. 用户评论情感分析(词频作为特征) 4. 搜索引擎优化(内容关键词密度计算)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值