最近陸陸續續經手了幾個公司專案的新功能,其中一個功能是要幫所有商品加上分類,然而在實作過程中卡關了一陣子,因此特別撰寫本文來記錄這次任務的幾種解法。
前言
我目前負責公司電商網站的維護,公司專案有個需求是要做出商品分類,在開發時我遇到一個 bug 解不出來,因此在六角學院社團附上 Demo 跟大家請教。
Demo:
卡關背景
邏輯
由於所有商品本身所建的分類較瑣細,而專案所需要呈現的分類涵蓋範圍較廣,因此資料需要經過額外的處理、比對,將所有商品歸納到各大分類之中,如果不屬於所列舉的分類,就把商品放到「其他」類。最後將所有分類與所屬的商品呈現在畫面上。
資料命名
在我附上的 Demo 中,allVariant 陣列是代表所有商品(裡面放的每個物件都是一個商品,type 屬性代表商品本身建的小分類),classifiedProducts 物件則是我想呈現的分類(types 屬性是陣列,放了多個商品本身所建的小分類;arr 屬性也是陣列,用來放過濾後的商品)。
目前作法
用類似雙迴圈的方法,同時迭代 allVariant 陣列與 classifiedProducts 物件,並用 if 判斷如果商品物件的 type 存在於分類物件的 types 陣列中,就把當前的商品物件 push 到當前分類的 arr;否則就 push 到「其他」類的 arr。
目前問題
「其他」類中,有許多筆重複的商品資料,且這些資料應該被放到別的分類中,卻都被放到「其他」類。
各種解法
卡在這個問題上已經超過一個早上了,最後真的走投無路於是還是來到六角學院的臉書社團發問,萬幸有不少同學(甚至還有助教)提供解法供我參考,以下就將他們的解法列出來。
解法一:while 迴圈法
提供這個方法的是玟憲同學,他同時還解說為何我的寫法會出錯:
this.allVariants用forEach後裡面那個for迴圈,第一個variant的type為'3d-screen-protector',就會跟this.classifiedProducts裡的每個key裡的types做比對,所以會跑 4 次。在「其他」的那個類別,塑料保護貼1出現 3 次的原因是:有一個types裡有['3d-screen-protector']所以被 push 進正確的arr,其餘 3 次都被 push 進otherProducts.arr。
1 | filter() { |
解法說明:
叫
variant一個一個去裡面this.classifiedProducts找,如果找到,就不要再找。this.classifiedProducts有 4 個物件,先把對應的 key 記下來(classifiedKey),跑while時,我需要記得我找到哪裡,idx 可以幫我。
所以就先找classifiedKey[0],如果有的話,要跳出迴圈(isMapping = false);
沒有的話繼續找classifiedKey[1]。
最後找到classifiedKey[idx] = 'otherProducts',就代表找完了,所以直接加進arr。
解法二:some() 法
此解法由葉子助教提供~~
我是用全部的資料去跑,用
some()的方式確認資料的type有沒有在分類中,有的話就推到對應的arr,沒有則推到其他。
1 | filter() { |
我發現這個解法與上一個解法有一些共通點:
- 都需要用一個變數來記錄「現在找到哪一個
this.classifiedProducts的 key」 - 都用額外用一個變數來記錄 type 是否存在於
this.classifiedProducts(布林值)
解法三:for..in 法
此解法由奕鋒同學提供:
這麼做也可以,只是要確保
otherProducts是最後一個迭代。
1 | filter() { |
解法四:find() + includes() 法
此解法由強者我同事在 Code Review 時提出,我看了差點膝蓋一軟給他跪下去 😂
1 | filter() { |
雖然最後是採用同事的解法,但其實其他同學提供的解法我也覺得很棒,其中使用了很多 ES6 的用法,我想我之後應該會時不時拿出來複習,因此特別寫這篇文以資紀錄。