淘寶sku算法淺析

????????最近項目遇到了一個難題,就是模仿淘寶上的選擇規(guī)格呀打,首先我先來解釋下什么是sku,sku(Stock Keeping Unit 庫存量單位)即庫存進出計量的基本單元,可以是以件搁嗓,盒,托盤等為單位箱靴。sku這是對于大型連鎖超市DC(配送中心)物流管理的一個必要的方法腺逛。上面的話可能你們沒有聽懂是什么意思,具體請打開手淘,選擇服裝類的產(chǎn)品(由于服裝類的產(chǎn)品可選規(guī)格較多衡怀,比較容易進行比較)棍矛。
????????當(dāng)時項目開始并不是采用這個sku算法,而是采用遍歷查詢的方式,將所有結(jié)果進行拆分抛杨,拆分成幾個不同屬性的集合够委;例如顏色、內(nèi)存怖现、大小等茁帽;然后通過用戶點擊按鈕,去遍歷后臺有無包括這種規(guī)格的商品(除了庫存為0)屈嗤;如果沒有則把按鈕變成灰色(即改變狀態(tài))潘拨;讓我們來分析下這種方案的優(yōu)缺點。

尺寸:5.0寸饶号、4.5寸
型號:土豪金铁追、紅、黑
內(nèi)存:128G茫船、64G

image.png

后臺可選的規(guī)格:

[
    ["4.5寸", "紅", "64G"],
    ["5.0寸", "土豪金", "128G"],    // 
    ["5.0寸", "黑", "128G"]
]

????????現(xiàn)在這幾種類型一共有2 * 3 * 2 = 12種排列組合脂信,然而只有3種組合是正確的(其中還要排除庫存為0的情況)一開始先保存好每一個按鈕和每一列的位置進入一個List<List<TagEnable>> 的數(shù)組中癣蟋,TagEnable記錄著每一個按鈕的狀態(tài)(0代表者正常,1代表選中狰闪,2代表不可選(庫存為0||無規(guī)格))疯搅;然后當(dāng)用戶點擊的時候,用Map<Integer,String> 記錄選中的按鈕和文字埋泵;并把每一個按鈕先設(shè)置為不可點擊幔欧,之后根據(jù)文字去對按鈕進行設(shè)置狀態(tài)。
????????這種算法是比較直接的一種實現(xiàn)丽声,但是很繁瑣礁蔗,循環(huán)嵌套循環(huán),可以簡單分析下算法復(fù)雜度雁社,如果sku屬性組合元素的總和數(shù)用m來表示浴井,可選的數(shù)據(jù)的長度是n的話,那么算法的步驟大概是m*n霉撵,這看起來好像不怎么復(fù)雜磺浙;不過,每次判斷一個sku組合是否和result中的 組合匹配徒坡,卻不是一個簡單的過程撕氧,實際上,這可以看做是一個字符串匹配的一個算法了喇完, 最簡單的還是使用正則匹配伦泥,m * n次正則匹配,這樣就不怎么快了吧锦溪。正則表達式很不穩(wěn)定不脯,萬一sku組合中有一些特殊字符,就可能導(dǎo)致一個正則匹配沒能匹配到我們想要的表達式刻诊。
而且防楷,當(dāng)用戶全部選中的時候,根據(jù)這種算法坏逢,只會出現(xiàn)一種情況域帐,就是未選中的全部都變成不可選(即變成灰色)赘被,這大大影響了用戶的體驗是整。如下圖:

第一種方案

????????sku算法是利用數(shù)學(xué)的集合思想來寫的。即先把可能的排列組合列出來民假,即取出集合中的所有子集浮入,數(shù)學(xué)上叫做冪集。
就是如果第一條數(shù)據(jù)["5.0寸", "黑", "128G"]可選羊异,
那么以下的組合肯定存在:

  • 5.0寸
  • 128G
  • 5.0寸事秀、黑
  • 5.0寸彤断、128G
  • 黑、128G
  • 5.0寸易迹、黑宰衙、128G
    所以,我們可以利用sku算法取出所有的組合睹欲,再根據(jù)這些組合的集合供炼,記為U,去判斷用戶點擊按鈕時窘疮,去設(shè)置其他按鈕的狀態(tài)袋哼;
    集合U.png

例如:當(dāng)用戶進行如下的選擇:5.0寸、128G
那么如何判斷 4.5寸這個按鈕的狀態(tài)呢闸衫?只需判斷4.5寸涛贯、128G是否可選(集合U是否存在(4.5寸-128G)這個組合并且?guī)齑娌粸?),以此類推:

4.5寸:   U是否包含于 4.5寸-128G   false
土豪金:  U是否包含于 5.0寸-土豪金-128G  true
紅:     U是否包含于 5.0寸-紅-128G  false
黑:     U是否包含于 5.0寸-黑-128G   true
64G:    U是否包含于 5.0寸-64G    false

于是乎蔚出,我們可以得出下列的結(jié)果:


圖3.png

優(yōu)化:

在使用淘寶的過程中弟翘,我發(fā)現(xiàn)他們可以根據(jù)用戶選擇按鈕的唯一值確定圖像(例如在這案例中,顏色是唯一的)身冬,當(dāng)用戶只選擇唯一值時衅胀,便可以確定其圖像


圖4.png
   StringBuilder stringBuilder = new StringBuilder();
            for (int i = 0; i < mUiData.getAdapters().size(); i++) {
                if (mUiData.getAdapters().get(i).getCurrentSelectedItem()!=null)
                    stringBuilder.append(mUiData.getAdapters().get(i)
                            .getCurrentSelectedItem().getAttributeMemberId()+";");
            }
            if (stringBuilder.length()!=0) {
                List<String> pricelist = new ArrayList<String>();
                for (Map.Entry<String, BaseSkuModel> entry : mUiData.getResult().entrySet()) {
//                            System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
                    if (mUiData.getSelectedEntities().size() == 1) {
                        if (entry.getKey().contains(stringBuilder.toString())) {
                            pricelist.add(entry.getValue().getPicture());
                        }
                    } else {
                        if (entry.getKey().contains(stringBuilder.substring(0, stringBuilder.length() - 1).toString())) {
                            pricelist.add(entry.getValue().getPicture());
                        }
                    }
                }
                List<String> newlist = ifRepeat(pricelist);
                BaseSkuModel baseSkuModel = new BaseSkuModel();
                if (newlist.size() == 1) {
//                Toast.makeText(MainActivity.this,""+,Toast.LENGTH_SHORT).show();
                    baseSkuModel.setPicture(newlist.get(0));
                    baseSkuModel.setPrice(mUiData.getBaseSkuModel().getPrice());
                    baseSkuModel.setFormatNum(mUiData.getBaseSkuModel().getFormatNum());
                    baseSkuModel.setStock(mUiData.getBaseSkuModel().getStock());
                } else {
                    baseSkuModel = mUiData.getBaseSkuModel();
                }
                mUiData.setCurrentskumodel(baseSkuModel);
            }else{
                mUiData.setCurrentskumodel(mUiData.getBaseSkuModel());
            }

做法是這樣子的:先遍歷原始數(shù)據(jù),如果用戶選擇的組合在原數(shù)據(jù)中是唯一的話酥筝,則可以確定其圖像滚躯。

最后附上github下載地址:

https://github.com/hfkai/SkuSelects

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市嘿歌,隨后出現(xiàn)的幾起案子掸掏,更是在濱河造成了極大的恐慌,老刑警劉巖宙帝,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丧凤,死亡現(xiàn)場離奇詭異,居然都是意外死亡步脓,警方通過查閱死者的電腦和手機愿待,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來靴患,“玉大人仍侥,你說我怎么就攤上這事≡Ь” “怎么了农渊?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長或颊。 經(jīng)常有香客問我砸紊,道長传于,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任醉顽,我火速辦了婚禮沼溜,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘游添。我一直安慰自己盛末,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布否淤。 她就那樣靜靜地躺著悄但,像睡著了一般。 火紅的嫁衣襯著肌膚如雪石抡。 梳的紋絲不亂的頭發(fā)上檐嚣,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天,我揣著相機與錄音啰扛,去河邊找鬼嚎京。 笑死,一個胖子當(dāng)著我的面吹牛隐解,可吹牛的內(nèi)容都是我干的鞍帝。 我是一名探鬼主播,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼煞茫,長吁一口氣:“原來是場噩夢啊……” “哼帕涌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起续徽,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤蚓曼,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后钦扭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體纫版,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年客情,在試婚紗的時候發(fā)現(xiàn)自己被綠了其弊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,643評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡膀斋,死狀恐怖梭伐,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情概页,我是刑警寧澤籽御,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布练慕,位于F島的核電站惰匙,受9級特大地震影響技掏,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜项鬼,卻給世界環(huán)境...
    茶點故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一哑梳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧绘盟,春花似錦鸠真、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至沦零,卻和暖如春祭隔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背路操。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工疾渴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人屯仗。 一個月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓搞坝,卻偏偏與公主長得像,于是被迫代替她去往敵國和親魁袜。 傳聞我的和親對象是個殘疾皇子桩撮,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,509評論 2 348

推薦閱讀更多精彩內(nèi)容