結對做業——WordCount進階版

結對做業——WordCount進階版

1. 地址


2.結對的PSP表格。

PSP2.1 開發流程 預估耗費時間(分鐘) 實際耗費時間(分鐘)
Planning 計劃 30 25
· Estimate 明確需求和其餘相關因素,估計每一個階段的時間成本 10 20
Development 開發 200 240
· Analysis 需求分析 (包括學習新技術) 20 20
· Design Spec 生成設計文檔 10 15
· Design Review 設計複審 10 45
· Coding Standard 代碼規範 30 25
· Design 具體設計 30 50
· Coding 具體編碼 150 180
· Code Review 代碼複審 10 15
· Test 測試(自我測試,修改代碼,提交修改) 30 55
Reporting 報告 60 85
· 測試報告 30 30
· 計算工做量 30 25
· 並提出過程改進計劃 30 15

三、解題思路描述。

關於此次的結對項目,咱們仔細閱讀並思考了題目的要求,明白了咱們要作的是:實現core模塊,實現詞組統計,實現自定義輸出以及程序的gui界面。html

  • core模塊
    該功能的實現難點主要在於對用戶一行輸入參數的讀取分析,不一樣命令行參數能夠隨意組合。能夠考慮將輸入的命令行字符串進行分割,用字符串數組存儲每個字符,if判斷進行實現或用switch選擇結構進行實現。git

  • 詞組統計
    對於指定長度的詞組,咱們將文章中的單詞按序存儲(除去分割符),再根據用戶指定的長度,順序輸出對應的單詞數。正則表達式

  • 自定義輸出
    能輸出用戶指定的前n多的單詞與其數量。涉及單詞的詞頻,對於詞組的詞頻,在將單詞按序存儲時創建map集合將單詞存入,以單詞頻數做爲value值。
    同時考慮到:輸入的詞組長度不該超過單詞組長度,不然輸出提示。
  • gui界面
    再將項目要求的功能基本實現後,進行gui編程,設計一個簡單便捷的圖形界面。編程


四、設計實現過程

在實現過程當中,我與小夥伴主要設計了三個類,包括讀寫文件的FileFunction類,對單詞存儲、排序、輸出等操做的word類,以及完成輸入、輸出操做的Main函數。數組

  • 如下是新增功能的主要設計實現過程:
    一、core模塊
    讀取用戶輸入的一行有多個命令行參數的命令,利用正則表達式將字符串分割,存入一個字符串數組中。將數組內容存入列表List中。循環讀取List中的內容,每讀取一個字符串,利用if結構判斷其與支持的功能參數是否對應,知足條件就執行相應的功能。
    讀到-i: 將後一個帶文件名/文件路徑的字符串賦給變量file。
    讀到-m:將後一個要讀取的字符串進行類型轉換,得到設置的詞組長度。
    讀到-n:將後一個要讀取的字符串進行類型轉換,得到最終要輸出的單詞的個數。
    讀到-o:後一個字符串內容即爲輸出結果的文件名/文件路徑。
Scanner sc = new Scanner(System.in);
        String file = null;
        int numM =0;\\詞組長度
        int numN =0;\\輸出的單詞個數
        String resultFile= null;\\生成文件路徑
        String str = sc.nextLine();
        String strarr[] = str.split("\\s+");\\空格分割字符串
        List<String> list = new ArrayList<>();
        for (String word:strarr) {
            list.add(word);
        }
//       分析對應的命令參數並執行對應功能
        for (int i = 0; i <list.size() ;i=i+2) {
            if (list.get(i).equals("-i")){
                file = list.get(i+1);
            }
            if (list.get(i).equals("-m")){
                numM = Integer.parseInt(list.get(i+1));
            }
            if (list.get(i).equals("-n")){
                numN = Integer.parseInt(list.get(i+1));
            }
            if (list.get(i).equals("-o")){
                resultFile = list.get(i+1);
            }
        }

二、詞組統計
當讀取用戶指定的詞組長度,就調用單詞操做類word中的Phrase函數。全局變量list即爲單詞表。字符串數組wordGroup用於存放詞組,數組長度爲詞組的數量(單詞表總數-詞組長度+1),利用雙重循環進行拼接單詞得到詞組。考慮到輸出的詞組應不重複,並統計詞組頻數,採用集合map進行操做,頻數爲value值。重寫Collections的sort函數將集合進行排序。函數

public String Phrase(int number) throws Exception{

        if(number>lists.size()) {
            return "the number is too long";
        }
 
        String wordGroup[] = new String[lists.size()-number+1];
        for (int i = 0; i <lists.size()-number+1 ; i++) {
            String phrase = lists.get(i);
            for (int j = i+1; j <i+number ; j++) {
                phrase = phrase+" "+lists.get(j);
            }
            wordGroup[i] = phrase ;
        }
        Map<String,Integer> treeMap =new TreeMap<String,Integer>();
        for (int i = 0; i < wordGroup.length; i++) {
            String s = wordGroup[i];
            if (!treeMap.containsKey(s)) {
                //不存在該詞組,存入集合
                treeMap.put(s, 1);
            } else {
                //存在將對應value加一
                int n = treeMap.get(s);
                treeMap.put(s, n + 1);
            }
        }
        //統計詞組頻數
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(treeMap.entrySet());
        
        Collections.sort(list, ((o1, o2) -> o2.getValue().compareTo(o1.getValue())));
        String s[] = new String[wordGroup.length];
        int i =0;
        for (Map.Entry<String,Integer>entry:list) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            s[i] = key + ": " + value;

            i++;
        }
        String string = s[0]+"\n";
        for (int j = 1; j <i ; j++) {
            string = string + s[j] + "\n";
        }


        return string ;
    }

三、自定義輸出
該功能與我的做業中的「統計詞頻並輸出頻數前10的單詞」有類似的地方。當對單詞完成存儲後,利用集合對全部單詞進行排序,最後再根據用戶指定的輸出單詞數n,按序輸出集合前n個單詞與詞頻。
sortWord函數中增長指定的輸出單詞數n,做爲傳入參數,便可完成自定義輸出。單元測試

public String sortWord(int number) throws Exception{
        Map<String, Integer> treeMap = new TreeMap<String, Integer>();

        for (int i = 0; i < lists.size(); i++) {
            String s = lists.get(i).toLowewerCase();//忽略大小寫
            if (!treeMap.containsKey(s)) {
                //不存在,就存入集合中
                treeMap.put(s, 1);
            } else {
                //存在就將value值加一
                int n = treeMap.get(s);
                treeMap.put(s, n + 1);
            }
        }
//單詞與頻數排序
        List<Map.Entry<String, Integer>> list = new ArrayList<Map.Entry<String, Integer>>(treeMap.entrySet());
        Collections.sort(list, ((o1, o2) -> o2.getValue().compareTo(o1.getValue())));
//        int n = 10;
        String s[] = new String[number];

        int i =0;
        for (Map.Entry<String, Integer> entry : list) {
            if (number-- == 0)
                break;
            String key = entry.getKey();
            Integer value = entry.getValue();
            s[i] = "<" + key + ">:" + value;
            i++;
        }//拼接字符串
        String string = s[0]+"\n";
        for (int j = 1; j <i ; j++) {
            string =string+ s[j]+"\n";
        }
        return string;

    }
  • FileFunction類
    包含讀取文件和寫出文件操做。將文件路徑做爲傳入參數。
public BufferedReader ReadFromFile(String path) throws IOException {
        //讀取文件

        File file = new File(path);
        if (!file.exists() || file.isDirectory()) {
            System.out.println("文件路徑不存在");
            throw new FileNotFoundException();
        }

        InputStreamReader isr = new InputStreamReader(new FileInputStream(path));
        BufferedReader br = new BufferedReader(isr);

        return br;
    }


    public  void WriteToFile(String path,String content) throws Exception {
     //寫出文件
        try {

            OutputStream out = new FileOutputStream(path);
            out.write(content.getBytes());
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
  • 圖形界面設計
    利用JFrame等簡單設計了程序的圖像界面。以下圖

五、單元測試

對於各個功能模塊分別提供一些測試樣例進行測試。學習

  • 如下是咱們進行的一些單元測試
  • FileFunctionTest:讀取文件和寫出文件操做FileFunction類的測試
class FileFunctionTest {
    FileFunction fi=new FileFunction();
    @Test
    void testReadFromFile() throws IOException {
    String path="input.txt";
    assertTrue(fi.ReadFromFile(path).equals("Monday Tuesday Wednesday Thursday"));
    }

    
    @Test
    void testWriteToFile() throws Exception {
    String outpath="output.txt";
    fi.WriteToFile(outpath, "hello i am test");
    fi.ReadFromFile(outpath).equals( "hello i am test");
    }

}

測試截圖:

測試

  • word類的單元測試

六、描述結對的過程,提供非擺拍的兩人在討論的結對照片

  • 在這次結隊過程當中,我收穫良多。與小夥伴一塊兒的結隊編程,帶來的不只是編程思想的對碰融合,更讓咱們在相互磨合、相互學習中深入體會到合做帶來的好處。咱們相互交流,相互學習,分享經驗。我看到了小夥伴與我徹底不同的思路和技能。在遇到不懂的地方我能獲得小夥伴的講解,增加知識。ui

  • 審查題目要求,咱們重新增功能的要求入手。針對一個功能函數,咱們會先各自思考,闡述彼此的思路,說明這樣作的緣由和好處。哪個更好,咱們就採起哪個的。好比在討論詞組時,咱們一塊兒琢磨詞組的定義,進一步肯定獲取一個完整詞組的方法,再次基礎上,會琢磨如何根據用戶指定的詞組長度去得到一個完整詞組。當將基本設計思路肯定之後會開始動手編程,一我的先根據討論好的思路編程,另外一我的會在旁邊看着,注意她編程過程當中出現的如變量命名不規範的問題。當部分代碼的測試出現錯誤時,咱們會一塊兒尋找出錯緣由,並討論如何修改它。咱們發現,兩我的找錯的效律會大於一我的的效律。同時咱們會在實現過程當中提出一些改進的意見和建議。好比對用戶輸入的詞組長度的判斷處理,在設計時沒有考慮到當詞組長度大於單詞總數的狀況,實現的時提了出來,恍然大悟應該注意到這種狀況。當沒法繼續編程下去的時候,咱們會互換角色。總之,咱們在結對合做的過程當中彼此受益。

相關文章
相關標籤/搜索