最近陸陸續續經手了幾個公司專案的新功能,其中一個功能是要幫所有商品加上分類,然而在實作過程中卡關了一陣子,因此特別撰寫本文來記錄這次任務的幾種解法。
前言
我目前負責公司電商網站的維護,公司專案有個需求是要做出商品分類,在開發時我遇到一個 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 的用法,我想我之後應該會時不時拿出來複習,因此特別寫這篇文以資紀錄。