淘宝sku算法浅析

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了淘宝sku算法浅析相关的知识,希望对你有一定的参考价值。

参考技术A

        最近项目遇到了一个难题,就是模仿淘宝上的选择规格,首先我先来解释下什么是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

仿制淘宝sku点击效果

1.依赖jquery,主要利用二维数组。

2.原生手写。

代码如下:

  1 <!DOCTYPE html>
  2 <html>
  3     <head>
  4         <meta charset="UTF-8">
  5         <title></title>
  6         <style>
  7             input{
  8                 width: 50px;
  9                 height: 35px;
 10                 background: orange;            
 11             }
 12         </style>
 13     </head>
 14     <body>
 15         <div class="container">
 16               <div class="row">
 17                 <input type="button" value="红" />
 18                 <input type="button" value="黄" />
 19                 <input type="button" value="蓝"/>
 20                 <input type="button" value="白"/>
 21                 <input type="button" value="军绿"/>
 22                 
 23             </div>
 24         
 25             <div class="row">
 26                 <input type="button" value="xl"/>
 27                 <input type="button" value="xxl"/>
 28                 <input type="button" value="xxxl"/>
 29             </div>
 30         
 31             <div class="row">
 32                 <input type="button" value="纯棉"/>
 33                 <input type="button" value="牛仔"/>
 34                 <input type="button" value="针织"/>
 35             </div>
 36             
 37             <div class="row">
 38                 <input type="button" value="A"/>
 39                 <input type="button" value="B"/>
 40                 <input type="button" value="C"/>
 41                 <input type="button" value="D"/>
 42                 <input type="button" value="E"/>
 43             </div>
 44           </div>    
 45     
 46         <div class="box">
 47             
 48         </div>
 49         
 50         
 51         <script src="jquery-3.2.1.min.js"></script>
 52         <script type="text/javascript">
 53             
 54             //给按钮添加选中取消标志
 55             $(".container .row input").attr("data-check",1);    
 56             //获取矩阵按钮
 57             function getBtn(ele){
 58                 var arr=[];
 59                 var contain = $(ele);
 60                 for(let i=0;i<contain.length;i++){
 61                     arr.push($.makeArray(contain[i].children));
 62                 }
 63                 return arr;
 64             }
 65             //生成二维数组
 66             var data = getBtn(".container .row"); 
 67             
 68         
 69             //判断点击的元素是否在二维数组中
 70             function getIndex(ele,map){
 71                 var res=[];
 72                 for(let i=0;i<map.length;i++){
 73                     for(let j=0;j<map[i].length;j++){
 74                         if(map[i][j] == ele){
 75                             res = [i,j];
 76                         }
 77                     }
 78                 }
 79                 return res;            
 80             }
 81            
 82             //生成默认值
 83             function init(data){
 84                 var arr = [];
 85                 for(let i = 0;i<data.length;i++){
 86                     arr.push([i,0]);
 87                 }
 88                 return arr;
 89             }
 90             var defaultVal = init(data);
 91             
 92             
 93             //渲染函数
 94             function myRender(s,data){
 95                     var str="";
 96                     for(let i = 0; i<data.length;i++){                    
 97                         str+=data[s[i][0]][s[i][1]].value+",";    
 98                     }                    
 99                     $(".box").append("<p>"+str+"</p>");
100             }
101             
102             //绑定点击事件
103             $(".container .row input").on("click",function(){
104                 var _this=$(this);
105                 if(_this.attr("data-check")==1){
106                     _this.attr("data-check",0);
107                     _this.css("background","gray");
108                     _this.siblings().css("background","orange")
109                     
110                     //判断在哪行那列
111                     var res = getIndex(_this[0],data);
112                     
113                     //插入要渲染的数据
114                     defaultVal.splice(res[0],1,res);
115                     
116                     //渲染数据
117                     myRender(defaultVal,data);
118                 
119             }else{
120                     _this.attr("data-check",1);
121                     _this.css("background","orange");
122             }
123         })
124         
125         </script>
126     </body>
127 </html>

事实上这个东西还有无限扩展,包括利用vue或react进行dom操作,还有各种接口,商品数量的操作等,时间有限,先这些。

以上是关于淘宝sku算法浅析的主要内容,如果未能解决你的问题,请参考以下文章

软件体系结构六大质量属性-浅析淘宝网

浅析|用协同过滤实现电商个性化推荐系统

iOS简单的插入排序算法浅析

浅析js模板引擎

浅析分布式系统

Raft 算法浅析