背单词工具

背单词工具

由于前段时间埋下的每天背十个单词的坑,所以有了这篇的文章。
工欲善其事必先利其器,背单词之前肯定需要有一个好工具。
虽然已经有好多成熟的背单词的app了,但是秉承着不用自己写的工具背单词的程序员不是好保安的原则。
那咱就自己写一个背单词的工具,你别管好不好用,我就乐意写。(●ˇ∀ˇ●)


推荐一个单词网站

单词网站

测试效果

在这里插入图片描述

在这里插入图片描述

准备工作

将单词学习笔记记录到markdown文本中

# 英语学习笔记

## 2023-09-07
___

**species**

n.种,物种,种类

例句:
1. This species is extremely rare. 这一物种极为罕见
2. Panadas are an endangered species. 大熊猫是一种濒危物种
3. There are many species of dog(s). 狗有许多种类
4. At least one otter species,the sea otter,has a large,often dominating,effect on the structure of its own habitat

**explanation**

adj.说明,解释,辩解

例句:
1. There was a logical explanation. 存在一个合理的解释
2. I think you owe us an explanation. 我认为你应当给我们一个解释
3. He didn't get a decent explanation. 他没有得到一个合理的解释

**significant**

adj.重大的;有效的;有意义的;值得注意的

例句:
1. There remained one significant problem. 还有一个非常重要的问题
2. Your work has shown a significant improvement. 你的工作有了显著的改进
3. The result are not statistically significant. 这些结果在统计上没有显著意义

**traditional**

adj.传统的;惯例的;

例句:
1. Most bosses are traditional. 大多数老板都很传统
2. Traditional values have been reasserted. 传统价值再次得到肯定
3. Most couples want a traditional wedding. 多数情侣希望举办一个传统的婚礼

**evidence**

n.证据,证明;迹象;明显
vt.证明

例句:
1. The evidence is against him. 证据对他不利
2. I had no concrete evidence. 我当时没有明确而具体的证据
3. Evidence is plentifully available. 证据俯拾即是

**temperature**

n.温度;体温;气温;发烧

例句:
1. Her temperature is normal. 她的体温正常
2. The temperature is plus four degrees. 温度为零上四度
3. The temperature has dropped considerably. 温度已大大降低

开始写代码

直接贴代码,将上面的单词markdown笔记放在resource目录中,将markdown读取到内存中解析。

解析markdown前,我们先分析一下markdown的规范,有规范才能解析。

  1. 英语单词是用** **包括着的
  2. 英语翻译是用 “adj”, “n”, “vt”, “v”, “vi”,“adv”,“prep” 前缀开头的,并且翻译有可能多个,没有包括所有的单词类型,后续有新的单词类型需要加上
  3. 例句是由 数字 开头的后几行

有了这几个规范我们就可以开始解析了。

先定义一个WordItem内部对象,用于接收单词数据。

@Data
static class WordItem {
    private String wordCn;

    private String wordEng;

    private List<String> exampleSentenceList;
}

逐行解析,从第一个单词到下一个单词前结束,将这段范围的内容封装成一个WordItem对象。

接下来就直接看代码吧,注释会写清楚的。


package com.tfxing.persondaily.utils;

import cn.hutool.core.collection.CollectionUtil;
import lombok.Data;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.*;

public class WordExamPlusUtils {

    @Data
    static class WordItem {
        private String wordCn;

        private String wordEng;

        private List<String> exampleSentenceList;
    }

    private List<Integer> numbers;
    private Random random;
    private Map<String,WordItem> wordMap;
    private List<String> keyList;

    private Boolean isEnd = false;

    public WordExamPlusUtils() {
        numbers = new ArrayList<>();
        random = new Random();
        wordMap = new HashMap<>();
        keyList = new ArrayList<>();

        // 匹配翻译的前缀
        List<String> wordCnPrefixList = Arrays.asList("adj", "n", "vt", "v", "vi","adv","prep");

        // 指定Markdown文件的路径
        String filePath = "src/main/resources/EnglishStudy.md";

        WordItem wordItem = null;
        // 用于接收单词翻译,多个翻译使用换行号分隔,打印时会直接换行
        StringJoiner wordCn = new StringJoiner("\n");
        // 例句列表
        List<String> exampleSentenceList = new ArrayList<>();

        try {
            // 创建一个BufferedReader来读取文件
            BufferedReader reader = new BufferedReader(new FileReader(filePath));

            String line;
            // 逐行读取文件内容并打印到控制台
            while ((line = reader.readLine()) != null) {
                if(skip(line)) { // 不符合前面梳理的规范的行直接跳过
                    continue;
                }

                // **开头的是英语单词,isEnd在遇到第一个单词时设置为了true,所以第二个单词后会走这个if的逻辑。将封装好的WordItem对象添加到wordMap中
                if(line.startsWith("**") && isEnd) {
                    String wordCnStr = wordCn.toString();

                    wordItem.setWordCn(wordCn.toString());
                    wordItem.setExampleSentenceList(exampleSentenceList);

                    wordMap.put(wordCnStr, wordItem);
                    keyList.add(wordCnStr);

                    wordCn = new StringJoiner("\n");
                    exampleSentenceList = new ArrayList<>();
                    wordItem = new WordItem();

                    String wordEng = line.replaceAll("\\*","");
                    wordItem.setWordEng(wordEng);

                    continue;
                }

                // 遇到第一个单词,将WordItem实例化,并设置英语单词的值
                if (line.startsWith("**")) {
                    wordItem = new WordItem();

                    String wordEng = line.replaceAll("\\*","");
                    wordItem.setWordEng(wordEng);

                    // 遇到第一个单词后,将isEnd设置为true
                    isEnd = true;
                }

                // 将翻译加到wordCn中
                if(containsWordPrefix(line,wordCnPrefixList)) {
                    wordCn.add(line);
                }

                // 数字开头的是翻译,将翻译添加到列表中
                if(isNumPrefix(line)) {
                    exampleSentenceList.add(line);
                }
            }

            // 关闭文件流
            reader.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            
            // 最后的单词没有下一个单词结束,所以在finally中处理最后一个单词的封装。
            String wordCnStr = wordCn.toString();

            wordItem.setWordCn(wordCn.toString());
            wordItem.setExampleSentenceList(exampleSentenceList);

            wordMap.put(wordCnStr, wordItem);
            keyList.add(wordCnStr);

            // 初始化数字列表,每个数字出现2次
            for (int i = 0; i < keyList.size(); i++) {
                numbers.add(i);
                numbers.add(i);
            }
        }
    }

    /**
     * 是否以数字.开头
     * @param line
     * @return
     */
    private boolean isNumPrefix(String line) {
        return line.matches("^\\d+\\..*");
    }

    /**
     * 以预设开头匹配
     * @param line
     * @param wordCnPrefixList
     * @return
     */
    private boolean containsWordPrefix(String line, List<String> wordCnPrefixList) {
        if(CollectionUtil.isEmpty(wordCnPrefixList)) {
            return false;
        }

        for (String wordCnPrefix : wordCnPrefixList) {
            if(line.startsWith(wordCnPrefix)) {
                return true;
            }
        }

        return false;
    }

    private boolean skip(String line) {
        return StringUtils.isBlank(line) ||
                line.startsWith("#") ||
                line.startsWith("_") ||
                line.startsWith("例句");
    }



    public Integer size() {
        return keyList.size();
    }

    public Integer roundSize() {
        return numbers.size();
    }


    public WordItem exam() {
        Integer index = getNextRandomNumber();

        if(Integer.valueOf(-1).equals(index)) {
            return null;
        }

        String key = keyList.get(index);
        WordItem wordItem = wordMap.get(key);

        return wordItem;
    }


    public int getNextRandomNumber() {
        if (numbers.isEmpty()) {
            return -1;
        }

        // 从数字列表中随机选择一个数字
        int randomIndex = random.nextInt(numbers.size());
        int randomNumber = numbers.get(randomIndex);

        // 从数字列表中移除已经被选中的数字
        numbers.remove(randomIndex);

        return randomNumber;
    }


	// 测试
    public static void main(String[] args) {
        WordExamPlusUtils wordExamUtils = new WordExamPlusUtils();

        Scanner scanner = new Scanner(System.in);

        Integer roundSize = wordExamUtils.roundSize();

        Integer total = roundSize;

        List<String> errorWordList = new ArrayList<>();

        while(roundSize > 0) {
            WordItem exam = wordExamUtils.exam();
            System.out.println(exam.getWordCn());
            System.out.println("请输入:");

            String input = scanner.next();
            if(exam.getWordEng().equalsIgnoreCase(input)) {
                System.out.println("正确");
            } else {
                System.out.println("错误");
                System.out.println(exam.getWordEng());

                errorWordList.add(exam.getWordCn() + " : " + exam.getWordEng());
            }

            for (String exampleSentence : exam.getExampleSentenceList()) {
                System.out.println(exampleSentence);
            }

            System.out.println();

            roundSize --;
        }

        int errorSize = errorWordList.size();
        int successSize = total - errorSize;
        BigDecimal rate = BigDecimal.valueOf(successSize).divide(BigDecimal.valueOf(total), 2, BigDecimal.ROUND_HALF_UP).multiply(BigDecimal.valueOf(100));
        System.out.println("本次测试,一共测试了" + total + "个单词\n正确个数:" + successSize + "\n错误个数:" + errorSize + "\n" + "正确率为:" + rate + "%");

        System.out.println();

        for (String errorWord : errorWordList) {
            System.out.println(errorWord);
        }
    }
}

一小段没有意义的话

写好了工具总算是可以认真背单词了吧。
。。。
不出意外的出意外是我的常态。
坚持了三天,背了三十个单词后,突然来了一个很复杂的需求。。。
时间给的也太紧了吧。我还要背单词呢。
看来只能先放一放了,虽然我有崇高的理想与追求。
但是生活不易,打工人还是得老老实实的打工才行啊。/(ㄒoㄒ)/~~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值