PTA 词频统计 (java)

请编写程序,对一段英文文本,统计其中所有不同单词的个数,以及词频最大的前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

 思路:

        通过正则表达式排除非题目要求符号,在对读取的数据加工

        然后排序,输入

 代码:

import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        ArrayList<vocabulary> list = new ArrayList<>();//定义了一个单词类的列表
        String regex = "[^a-zA-Z0-9#_]";//正则表达式:识别除字母,数字,#和_线的符号
        while (true) {
            String str = sc.nextLine();//获取输入
            String[] allStr = str.replaceAll(regex, " ").split(" ");
            //一步一步看
            //replaceAll() 通过正则表达式将非表达式的符号转化为空格
            //split() 通过对空格进行切割化为数组

            for (String s : allStr) {
                if (s.equals("#")) {//判断是否读取结束
                    printfList(list);//定义了一个方法将全部单词统计词频后按题目需求打印
                    System.exit(0);//停止虚拟机的运行
                }
                if(s.equals("")) {//判断是否为空串,这个大多是在一行中什么也没输入直接回车造成的
                    continue;
                }
                if (s.length() >= 15) {//判断单词长度是否大于等于15
                    s = s.substring(0, 15);
                }
                int i;
                for (i = 0; i < list.size(); i++) {
                    vocabulary vocabulary = list.get(i);//获取列表里的单词
                    String name = vocabulary.getName();//获取单词名字
                    if (s.equalsIgnoreCase(name)) {//判断是否与列表里的单词相同
                        int num = vocabulary.getNum();//获取单词词频
                        num++;//自增
                        vocabulary.setNum(num);//修改
                        break;
                    }
                }
                if (i == list.size()) {//列表中没有相同的单词
                    list.add(new vocabulary(s.toLowerCase(), 1));//自立门户
                }
            }
        }
    }

    private static void printfList(ArrayList<vocabulary> list) {//全部单词统计词频后按题目需求打印
        System.out.println(list.size());//打印一共多少单词

        list.sort((o1, o2) -> o2.getNum() == o1.getNum() ? o1.getName().compareTo(o2.getName()) : o2.getNum() - o1.getNum());
        //一步一步看
        //这里用了一个java的lambda表达式 和 三元表达式
        //sort() -> {} 此处的lambda表达式是对列表的单词按词频排序
        //o2.getNum() == o1.getNum() ? o1.getName().compareTo(o2.getName()) : o2.getNum() - o1.getNum()
        //这一串三元表达式判断两个单词的词频是否相同
        //o1.getName().compareTo(o2.getName()) 相同则按字母字典顺序来排序
        //o2.getNum() - o1.getNum() 否则降序排序

        int num = (int) (list.size() * 0.1);//取得前10%的单词
        for (int i = 0; i < num; i++) {//for打印
            vocabulary vocabulary = list.get(i);
            System.out.println(vocabulary);
        }
    }
}

class vocabulary {
    private String name;//单词名字
    private int num;//词频


    public vocabulary() {
    }

    public vocabulary(String name, int num) {
        this.name = name;
        this.num = num;
    }

    /**
     * 获取
     *
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     *
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     *
     * @return num
     */
    public int getNum() {
        return num;
    }

    /**
     * 设置
     *
     * @param num
     */
    public void setNum(int num) {
        this.num = num;
    }

    public String toString() {
        return num + ":" + name;
    }
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值