iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 21
0
自我挑戰組

30天找回寫程式手感計劃!!!系列 第 21

Day21 - 正規表示式 x JavaScript x JSON (解決篇)~阿母我出運啦!

  • 分享至 

  • xImage
  •  

前兩天課題就是要把各間藥局剩餘口罩數量資料集中的各間藥局營業時間 parsing 出來,
再做成下拉式選單顯示該時段有哪些藥局有瑩業,
但前兩天程式寫的真是有夠爛,
一直在重複程式碼,
小的心有不甘,
今天再度挑戰,
終於寫到我滿意了!!!!!
灑花✧*。٩(ˊᗜˋ*)و✧*。
https://www.playsport.cc/upload/forum/14649586885900.jpg

正片開始

挑戰前的思考

前幾天我都沒有全盤大概思考過做法,
想到什麼打什麼,
才會導致程式亂糟糟,
所以今天挑戰前我用筆稍微把想法寫下來,
也順便順一下這個題目的條理。
前置處理:
0. 有一個陣列存在著 "星期一上午、星期二上午" 等,另外再有個陣列存各時段的藥局有哪些。
藥局清單 ["星期一上午"] = [
{Name:"承都藥局",County:"新北市",Town:"三重區"},
{Name:"北聯藥局",County:"新北市",Town:"三重區"},
{Name:"祥安藥局",County:"花蓮縣",Town:"蘆洲區"},
.......
]
也就是把 時段當該陣列的索引值 這樣。

再來,拿到每筆藥局資料:

  1. 先用 "、" 將 "星期一上午、星期二上午" 等字串分開。
  2. 再檢查以上陣列,其中有 "休診" 字眼,就要將該元素從陣列中移除 (splice)。
  3. 將以上陣列元素的看診、休診 trim 掉,只留 "星期一上午" 這樣的字眼。
  4. 將每個時段拿出來判斷,如果該藥局有落在該時段,就存在該時段的藥局清單中。
    例如,承都藥局的營業時間 (available) 有含 "星期一上午",
    則將該筆資料存進 ["星期一上午"] 的陣列中。

良好習慣:一樣從靜態資料開始

  • 先把 "星期一上午" 等時段存成陣列,方便之後比較。
let openTimeRelation = []; // 存放星期一上午、星期二上午等字眼
let availStr = "星期一上午看診、星期二上午看診、星期三上午看診、星期四上午休診、星期五上午看診、星期六上午看診、星期日上午休診、星期一下午看診、星期二下午看診、星期三下午看診、星期四下午看診、星期五下午看診、星期六下午看診、星期日下午休診、星期一晚上看診、星期二晚上看診、星期三晚上看診、星期四晚上看診、星期五晚上看診、星期六晚上看診、星期日晚上休診";
let availArray = availStr.split("、");
// 把星期幾上午先存一次字串陣列
for ( let i=0;i<availArray.length;i++ ){
    openTimeRelation.push(availArray[i].substring(0,5)); // 0,5 會拿到 星期一上午 的字串
}
  • 再來將有 休診 字眼的元素移出陣列,之後再將每個元素最後 看診 的字眼 trim 掉。
for ( let i=0;i<availArray.length;i++ ){
    if ( availArray[i].match("休診") !== null ){
        availArray.splice(i, 1); // 有休診的就移出陣列
        i--; // 因為該元素移出陣列,下一個元素會遞補上來,如果沒有將索引值-1,會漏掉被遞補上來的元素沒被處理到
        continue; // 遇到 "休診" 不做,回到迴圈最一開始處理
    }
    availArray[i] = availArray[i].substring(0,5); // 每個元素存成 星期一上午 (後面看診字眼不要)
    ..... (略)
}
  • 再來是比較關鍵的地方,前面提到想要將時段變成陣列索引值,
    該藥局若該時段有營業,就將該藥局丟進 ["時段"] 的陣列中。
    這邊我最初是這樣寫的:
for ( let j=0;j<openTimeRelation.length;j++ ){
    // console.log(openTimeRelation[j]);
    if ( availArray[i].indexOf(openTimeRelation[j])>=0 ){   
        openTimeStoreList[openTimeRelation[j]].push({Name:"承都藥局",County:"新北市",Town:"三重區"});
    }
}

這邊我一直出現以下問題,
說 openTimeStoreList[openTimeRelation[j]].push 不能使用 push 之類的。
卡了很久才想到,
因為並沒有先宣告好 openTimeStoreList[openTimeRelation[j]] 是陣列,
所以用陣列的 push 才會出問題。
因此前面要再加判斷式,
如果 openTimeStoreList[openTimeRelation[j]] 不存在,則要宣告為空白陣列,
像這樣:

if ( !openTimeStoreList[openTimeRelation[j]] ){
    openTimeStoreList[openTimeRelation[j]] = [];
} 

這樣後面再使用 push 才不會出問題。

  • 為了確認前面寫的邏輯沒問題,
    我有用 迴圈 + console.log 確認看看。
for ( let i=0;i<openTimeRelation.length;j++ ){
    if ( openTimeStoreList[openTimeRelation[i]] ){
        console.log(`第 ${i} 個 ${openTimeRelation[i]}`);
        for ( let j=0;j<openTimeStoreList[openTimeRelation[i]].length;j++ ){
            console.log(openTimeStoreList[openTimeRelation[i]][j]);  
        }
    }
}

https://ithelp.ithome.com.tw/upload/images/20200927/201298730gROxKFXil.png
確定重要的邏輯 OK 後,
就將頁面長出 星期、時段 兩個下拉式選單,
下面就依據所選顯示出結果。
都沒問題就將靜態的 3 筆資料改成動態取資料,
再加上一些時段及間數的顯示。
https://ithelp.ithome.com.tw/upload/images/20200927/20129873fnvKZ29nzV.png
耶,本日打完收工!

[後記]

昨天說要改的地方:
1. 時段為什麼並沒有弄在第二個下拉式選單,因為我發現好像有問題,這邊要再 debug 個 => Done
2. 重複程式碼的地方真的太多,這真的要 tune => Done
3. 今天的寫法不好,資料一多就跑得有點慢,要換個寫法 => Done

把寫法改過發現 performance 整個也大提升!
今天能改出來真的很開心!
而且今天也深刻體會到動工前要先大概思考過擬好步驟真的滿重要的,
雖然後來實際動工遇到了之前思考時沒想到的問題,
但大概走向八九不離十,
有規劃過寫程式時也會比較有條理,
不會想到什麼就亂寫,
導致程式亂糟糟。

而且原來寫程式會提振精神(?),
本來因為昨天一整天都在外面滿累的,
今天一整天在家昏昏沉沉,
沒想到寫完程式整個人都神清氣爽的呢!XD

然後眼尖的人可能有發現,
其實資料集有放這麼一個資料:

"service_periods": "NNNNNNYNNNNNNYNNNNNYY"

觀察了一下,
這一行有 21 個值,
N 是看診,Y 是休診,
所以前面 parsing 字串 pa 得很辛苦的我是在......?
不過有練習到比較重要啦XD

[本日程式碼]

Codepen

[進入最後一週前的碎念(?)]

其實離挑戰結束只剩不到 10 天,
好像應該要來面對我之前號稱說要面對的 JavaScript 最終作業了orz
但也總不能直接將最終作業的挑戰過程寫在這,
為難中XD
再讓我想想QAQ


上一篇
Day20 - 正規表示式 x JavaScript x JSON ( 2/2 )
下一篇
Day22 - 「原來你家養了一頭 localStorage 啊!」~ 網頁 local 端的資料庫(認識篇)
系列文
30天找回寫程式手感計劃!!!36
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言