⑴ 淘寶sku演算法淺析
最近項目遇到了一個難題,就是模仿淘寶上的選擇規格,首先我先來解釋下什麼是sku,sku(Stock Keeping Unit 庫存量單位)即庫存進出計量的基本單元,可以是以件,盒,托盤等為單位。sku這是對於大型連鎖超市DC(配送中心)物流管理的一個必要的方法。上面的話可能你們沒有聽懂是什麼意思,具體請打開手淘,選擇服裝類的產品(由於服裝類的產品可選規格較多,比較容易進行比較)。
當時項目開始並不是採用這個sku演算法,而是採用遍歷查詢的方式,將所有結果進行拆分,拆分成幾個不同屬性的集合;例如顏色、內存、大小等;然後通過用戶點擊按鈕,去遍歷後台有無包括這種規格的商品(除了庫存為0);如果沒有則把按鈕變成灰色(即改變狀態);讓我們來分析下這種方案的優缺點。
尺寸:5.0寸、4.5寸
型號:土豪金、紅、黑
內存:128G、64G
現在這幾種類型一共有2 * 3 * 2 = 12種排列組合,然而只有3種組合是正確的(其中還要排除庫存為0的情況)一開始先保存好每一個按鈕和每一列的位置進入一個List<List<TagEnable>> 的數組中,TagEnable記錄著每一個按鈕的狀態(0代表者正常,1代表選中,2代表不可選(庫存為0||無規格));然後當用戶點擊的時候,用Map<Integer,String> 記錄選中的按鈕和文字;並把每一個按鈕先設置為不可點擊,之後根據文字去對按鈕進行設置狀態。
這種演算法是比較直接的一種實現,但是很繁瑣,循環嵌套循環,可以簡單分析下演算法復雜度,如果sku屬性組合元素的總和數用m來表示,可選的數據的長度是n的話,那麼演算法的步驟大概是m*n,這看起來好像不怎麼復雜;不過,每次判斷一個sku組合是否和result中的 組合匹配,卻不是一個簡單的過程,實際上,這可以看做是一個字元串匹配的一個演算法了, 最簡單的還是使用正則匹配,m * n次正則匹配,這樣就不怎麼快了吧。正則表達式很不穩定,萬一sku組合中有一些特殊字元,就可能導致一個正則匹配沒能匹配到我們想要的表達式。
而且,當用戶全部選中的時候,根據這種演算法,只會出現一種情況,就是未選中的全部都變成不可選(即變成灰色),這大大影響了用戶的體驗。如下圖:
sku演算法是利用數學的集合思想來寫的。即先把可能的排列組合列出來,即取出集合中的所有子集,數學上叫做冪集。
就是如果第一條數據["5.0寸", "黑", "128G"]可選,
那麼以下的組合肯定存在:
例如:當用戶進行如下的選擇:5.0寸、128G
那麼如何判斷 4.5寸這個按鈕的狀態呢?只需判斷4.5寸、128G是否可選(集合U是否存在(4.5寸-128G)這個組合並且庫存不為0),以此類推:
於是乎,我們可以得出下列的結果:
在使用淘寶的過程中,我發現他們可以根據用戶選擇按鈕的唯一值確定圖像(例如在這案例中,顏色是唯一的),當用戶只選擇唯一值時,便可以確定其圖像
做法是這樣子的:先遍歷原始數據,如果用戶選擇的組合在原數據中是唯一的話,則可以確定其圖像。
https://github.com/hfkai/SkuSelects
⑵ ios SKU 組合演算法
通俗來講,一個SKU 就是商品在規格上的一種組合,比如說,一件衣服 有紅色 M號的 也有藍色 L號的 ,不同的組合就是不同的SKU
近段時間,剛好遇到要在商品詳情頁購買商品的時候,實現選擇不同規格組合的sku,預判無庫存sku選項置灰,減少客戶不必要sku的選擇。
網上搜尋了一大批有關sku選擇演算法的文章,然後被各路大神的一頓操作秀得一臉懵逼,簡單來說就是沒看懂。。。
當然基於以上參考得到的靈感,終於總結出來了一種簡單易用通俗易懂的sku選擇演算法,思路簡單,唯一的bug是sku數據有n多層的時候,計算量大耗內存。當然現在手機的運算能力都是杠杠的,正常來說商品的sku也不會有幾十上百層那麼誇張。
接下來我先捋一下思路吧!
Tips: sku 有三種狀態,可選(正常),不可選(置灰),已選中(高亮),
一,sku演算法初版:計算所有sku的組合 與 有庫存sku的組合的交集,交集裡面的sku為可選項,反之其他sku為不可選。
1.計算所有sku的組合-->集合A
A = ["34,61,66" , "34,61,67" , ......]
2.計算有庫存的sku的組合 -->集合B
一般是從後台伺服器返回的 eg:
3. 計算集合A與集合B的交集,交集裡面的所有元素就是初始時所有可選sku ID ,反之其他sku ID就是置灰(無庫存不可選狀態)
4.以上三步就是簡易的sku演算法核心思路,彈出規格框時,計算集合A和集合B的交集,得到初步賽選結果,告訴客戶,哪些sku無庫存不可選置灰顯示,可選的為正常狀態顯示,減少客戶做不必要的選擇操作。
5.當然,細心的你很快就會發現這樣的sku演算法會導致無法判斷出,已選sku的兄弟節點是否可選的bug。
二,優化兄弟節點的可選狀態判斷bug
1.如上圖 已選Platform 屬性的 34,長度屬性的 62 , 我們要判斷的已選sku兄弟節點屬性分別是Platform 屬性的 35,長度屬性的 61。
2.即:
要判斷 長度屬性的 61是否為可選,就要判斷,34,61這樣的組合是否屬於有庫存組合裡面子集,是:可選,不是: 不可選。
同理:
要判斷 Platform 屬性的 35是否為可選,就要判斷,35,62這樣的組合是否屬於有庫存組合裡面子集,是:可選,不是: 不可選。
3.細心的你肯定發現了規律,34,61 或者 35,62 這樣的組合都有一個共同點
即:包含n個已選skuID,n = 已選sku個數-1 .
三,計算兄弟節點是否可選
1,計算已選sku ID 同類屬性的組合 ==集合C 即:計算Platform 屬性和長度屬性的組合
集合C = ["34,61","34,62","35,61","35,61","35,62"]
2.計算已選skuID的子集 ==集合D 即:計算 [34,62]的子集
集合D = ["34","62","34,62"]
3.從集合D裡面篩選出,含有n個已選skuID的子集(n = 已選sku個數-1 )==集合E
集合E = ["34","62"]
4.最後計算可選兄弟節點組合,集合C裡面的組合只要是含有集合E裡面的元素都是可選兄弟節點組合
可選兄弟節點組合F = 【集合C裡面的組合只要是含有集合E裡面的元素】
5.
兄弟節點可選skuID = 【(集合A與集合B的交集的skuID集合)再與 集合F 的並集 】
四,整理
1.篩選有庫存的sku組合為可選sku 其餘為不可選sku
2.計算兄弟節點可選sku
3.可選sku正常顯示,不可選sku置灰,已選sku高亮
附Demo: sku演算法demo
五,拓展一下