7-1 词频统计 (30 分)

词频统计

参考:
对参考的代码进行了一些补充和修改,大体思路没变
并不是想说这题多难,只是在这题可以用STL的很多结构帮助解题,所以能让代码变得很简单

题目

请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前10%的单词。
所谓“单词”,是指由不超过80个单词字符组成的连续字符串,但长度超过15的单词将只截取保留前15个单词字符。而合法的“单词字符”为大小写字母、数字和下划线,其它字符均认为是单词分隔符。
输入格式:
输入给出一段非空文本,最后以符号#结尾。输入保证存在至少10个不同的单词。
输出格式:
在第一行中输出文本中所有不同单词的个数。注意“单词”不区分英文大小写,例如“PAT”和“pat”被认为是同一个单词。
随后按照词频递减的顺序,按照词频:单词的格式输出词频最大的前10%的单词。若有并列,则按递增字典序输出。
输入样例:
This is a test.

The word "this" is the word with the highest frequency.

Longlonglonglongword should be cut off, so is considered as the same as longlonglonglonee. But this_8 is different than this, and this, and this...#
this line should be ignored.
输出样例:(注意:虽然单词the也出现了4次,但因为我们只要输出前10%(即23个单词中的前2个)单词,而按照字母序,the排第3位,所以不输出。)
23
5:this
4:is

思路

题目要求记录词频,那就记录每个词出现的次数
由于‘#’表示结束,那么就要逐字读入进行判断,但这要这么变成一个单词呢?只要把每个读到的字符接在字符串的后面就行了
然后可以构建一个列表,表中有每个单词及其出现次数

用到的结构及函数

begin()和end()函数

基本上线性存储类类型都会有的结构(vector,map),其实就是快速定位到第一个(通常下标是0)和最后一个数据。要注意的是他们可以直接进行加减运算
通常在初始化或者函数中用到

vector<pair<string ,int>> v(ma.begin(), ma.end());    //定义一个pair<string ,int>类型的数组,并且数组第一个数据为ma的第一个数据,最后一个数据为ma的最后一个数据
sort(v.begin(), v.end(), cmp);    //将v从v 的第一个到最后一个数据根据自定义的比较函数cmp进行分类。sort的自定义比较函数之后会说
//来自C++Reference的样例
int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               // 32 71 12 45 26 80 53 33 (对前八个数排序)

  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33 (对前四个数排序)

pair(对组)

pair是C++定义的模板类型,可以同时存储两个类型的数据,其实可以用结构体实现的呢

pair<string, int> a    //定义
a.firts="Hello World";    //对第一个数据进行操作
a.second="3";             //对第二个数据进行操作

map

先来看看C++reference的定义

/*
Maps are associative containers that store elements formed by a combination of a key value and a mapped value, following a specific order.
In a map, the key values are generally used to sort and uniquely identify the elements, while the mapped values store the content associated to this key.
The types of key and mapped value may differ, and are grouped together in member type value_type, which is a pair type combining both:
*/

typedef pair<const Key, T> value_type;

其实,我们可以把map理解为一个容器,其内部存的是一组键值对,即两个不同类型的数据。
可以理解为“关键字”以及“关键字的值”(没错,和pair很像)

vector(容器)

vector可以看成加强版数组,用于储存相同类型的多个数据。这里要介绍他的排序函数sort()
从C++reference中可以找到以下例子

 int myints[] = {32,71,12,45,26,80,53,33};
  std::vector<int> myvector (myints, myints+8);               //初始化为 32 71 12 45 26 80 53 33(myints的前八个放入vector)

  // using default comparison (operator <):
  std::sort (myvector.begin(), myvector.begin()+4);           //(12 32 45 71)26 80 53 33

  // using function as comp
  std::sort (myvector.begin()+4, myvector.end(), myfunction); // 12 32 45 71(26 33 53 80)

  // using object as comp
  std::sort (myvector.begin(), myvector.end(), myobject);     //(12 26 32 33 45 53 71 80)

可以看出sort()其实可以自己加函数进行排序,不过如果自己每加的话就默认非降序排列
那如果我要自己加函数要怎么加呢?
参考:【C++】从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法
首先自定义比较函数的返回值是bool型的,这里给出一个例子

    bool comp(int a,int b){
        return a>b;
    }

    sort(v.begin(), v.end(), comp);

比较时sort函数根据comp函数进行判断输的大小,系统默认a<b时返回真,于是从小到大排,而我的comp函数设定为a>b时返回为真,那么最终得到的排序结果也相应的从小到大变成从大到小。其实可以这样理解:排序结束后,a是前面的数,b是后面的数,我们的自定义函数是为了定义a与b的关系
再让我们来看代码中的例子

bool cmp(pair<string, int> a, pair <string, int> b) {
    bool result = false;
    if (a.second == b.second&&a.first < b.first) {
        result = true;
    }
    else if (a.second > b.second) {
        result = true;
    }
    return result;
}

sort(v.begin(), v.end(), cmp);

那么上述式子就表明,对vector中的第一个数据到最后一个数据排列。
因为vector中的数据类型是pair,根据自定义的比较函数,当pair的second(词语出现次数)相等时,first(单词)小的在前面(若有并列,则按递增字典序输出)。

代码

#include <iostream>
#include <string>
#include <vector>
#include <map>
#include <algorithm>

using namespace std;

bool cmp(pair<string, int> a, pair <string, int> b);

int main() {
    char ch;
    string s;   //字符串用于记录一个单词
    map<string, int> ma;    //map记录词频,string代表的单词出现次数为int
    do {
        ch = getchar();
        //当读到的是合法字符(大小写字母、数字下划线)
        if ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z') || (ch >= '0'&&ch <= '9') || ch == '_') {
            if (s.size() <= 14) {   //当长度为14时再进行一次接入,长度为15就停止接入
                if (ch >= 'A'&&ch <= 'Z') {     //把大写换成小写
                    ch += 32;
                }
                s += ch;    //把单个字符ch接到字符串s后,string中有运算符重载所以加法表示接在后面
            }
        }
        else {      //当不是合法字符就表示这个词读取结束了,出现次数+1
            if (s.size() > 0) {
                ma[s]++;
            }
            s.clear();      //清空字符串以统计下一个单词
        }
        if (ch == '#') {    //读到#退出循环
            break;
        }
    } while (ch != '#');
    vector<pair<string ,int>> v(ma.begin(), ma.end());        //存储pair的一个数组(把vector理解为增强版的数组)
    sort(v.begin(), v.end(), cmp);
    cout << v.size() << endl;
    int cnt = (int)(ma.size()*0.1);
    for (int i = 0; i < cnt; i++) {
        cout << v[i].second << ":" << v[i].first << endl;
    }
    return 0;
}

//利用pair数据,每个pair数据都含有一个string数值和int数值
//
bool cmp(pair<string, int> a, pair <string, int> b) {
    bool result = false;
    if (a.second == b.second&&a.first < b.first) {
        result = true;
    }
    else if (a.second > b.second) {
        result = true;
    }
    return result;
}

原文地址:https://www.cnblogs.com/luoyang0515/p/10991972.html

时间: 2024-08-04 20:02:51

7-1 词频统计 (30 分)的相关文章

201671010441徐浩杰 词频统计软件项目报告

实验二.软件工程个人项目 一.需求分析 尝试按照<构建之法>第2章中2.3所述PSP流程,使用JAVA编程语言,独立完成一个英文文本词频统计的软件开发.软件基本功能要求如下: •程序可读入任意英文文本文件,该文件中英文词数大于等于1个. •程序需要很壮健,能读取容纳英文原版<哈利波特>10万词以上的文章. •指定单词词频统计功能:用户可输入从该文本中想要查找词频的一个或任意多个英文单词,运行程序的统计功能可显示对应单词在文本中出现的次数和柱状图. •高频词统计功能:用户从键盘输入高

词频统计-功能一

一.完成一个小程序 我 拿到这个题目之后,就决定用最不熟悉的c#来实现,因为老师说不懂的去学才会有进步.布置任务后的第二天就开始去图书馆借了两本书<c#从入门到精髓>,<c#项目实战>,拿到书之后看了入门书<c#从入门到精髓>,看书的过程时痛苦的,因为发现大二选修课学的c#全交还给老师了,只能重头再学了.唯一有点印象的就是窗口应用程序,基于UI的设计. 写代码首先需要工具,由于电脑上没有visual studio的安装包,当时求助了度娘. 如果没有安装包的同学们,可以借

pta08-图7 公路村村通 (30分)

08-图7 公路村村通   (30分) 现有村落间道路的统计数据表中,列出了有可能建设成标准公路的若干条道路的成本,求使每个村落都有公路连通所需要的最低成本. 输入格式: 输入数据包括城镇数目正整数N(≤1000)和候选道路数目M(≤3N):随后的M行对应M条道路,每行给出3个正整数,分别是该条道路直接连通的两个城镇的编号以及该道路改建的预算成本.为简单起见,城镇从1到N编号. 输出格式: 输出村村通需要的最低成本.如果输入数据不足以保证畅通,则输出−1,表示需要建设更多公路. 输入样例: 6

软件工程第二次作业 词频统计

1.项目名称:词频统计 2.代码地址:https://coding.net/u/songyuu/p/python_wf/git 3.代码如下: 1 import os 2 import re 3 import collections 4 #print(os.getcwd()) #显示wf.py路径 5 #print(os.listdir())#显示目录下的文件 6 file_name=input("wf ") 7 if not os.path.isfile(file_name+'.tx

组合数据类型练习,英文词频统计实例

1.由字符串创建一个作业评分表,做增删改查询统计遍历操作,例如查询第一个3分的下标,统计1分的同学有几个,3分的同学有几个,增删改查等等. 2.字典实例:建立学生学号成绩字典,做增删改查遍历操作. 3.列表,元组,字典,集合的遍历. 4.英文词频统计实例 news = '''When I was young I'd listen to the radio Waiting for my favorite songs When they played I'd sing along, It make

5-24 树种统计 (25分)

5-24 树种统计   (25分) 随着卫星成像技术的应用,自然资源研究机构可以识别每一棵树的种类.请编写程序帮助研究人员统计每种树的数量,计算每种树占总数的百分比. 输入格式: 输入首先给出正整数N(\le 10^5≤10?5??),随后N行,每行给出卫星观测到的一棵树的种类名称.种类名称由不超过30个英文字母和空格组成(大小写不区分). 输出格式: 按字典序递增输出各种树的种类名称及其所占总数的百分比,其间以空格分隔,保留小数点后4位. 输入样例: 29 Red Alder Ash Aspe

第二周-词频统计更新

词频统计功能新增: HTTPS:https://git.coding.net/li_yuhuan/WordFrequency.git SSH:[email protected]:li_yuhuan/WordFrequency.git 代码: static void Main(string[] args) { string str = ""; int length = args.Length; switch (length) { case 0: { string line = Conso

个人项目----词频统计WEB(部分功能)

需求分析 1.使用web上传txt文件,对上传的txt进行词频统计. 2.将统计后的结果输出到web页面,力求界面优美. 3.在界面上展示所给url的文章词频统计,力求界面优美. 3.将每个单词同四.六级词库进行比对,统计所传txt文件中四.六级单词涵盖率. 4.在3的基础上,展示文章中前10%单词中的覆盖百分比,词频前50%单词.词频前80%单词的覆盖百分比. 由于能力有限,学习了很久,到目前为止之完成了第一个功能,并对结果进行了输出,界面部分还有待学习. 代码实现 创建了两个JSP界面,up

java词频统计——改进后的单元测试

测试项目 博客文章地址:[http://www.cnblogs.com/jx8zjs/p/5862269.html] 工程地址:https://coding.net/u/jx8zjs/p/wordCount/git ssh://[email protected]:jx8zjs/wordCount.git 测试用例: 1. 1 My English is very very pool 2.地址 [http://www.gutenberg.org/files/2600/2600-0.txt] 待测单