设为首页收藏本站

PHPIN.NET

 找回密码
 立即注册
查看: 302|回复: 0

[其他相关] SKU前端算法DEMO

[复制链接]

374

主题

381

帖子

2558

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
2558
发表于 2016-6-21 17:41:12 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
SKU前端算法DEMO

类似淘宝的SKU前端算法DEMO,code:
  1. <!doctype html>
  2. <html lang="zh-cn">
  3. <head>
  4. <meta charset="utf-8" />
  5. <title>SKU demo</title>
  6. <style type="text/css">
  7. *,body,button,input,textarea,select{text-rendering:optimizeLegibility;-moz-osx-font-smoothing:grayscale;}
  8. body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td{margin:0;padding:0;}
  9. table{border-collapse:collapse;border-spacing:0;}
  10. fieldset,img{border:0;}
  11. address,caption,cite,code,dfn,em,strong,th,var{font-style:normal;font-weight:normal;}
  12. ol,ul{list-style:none;}
  13. caption,th{text-align:left;}
  14. h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal;}
  15. q:before,q:after{content:'';}
  16. abbr,acronym{border:0;}
  17. .bh-sku-selected{color:red;}
  18. </style>
  19. </head>
  20. <body>
  21.   <div>
  22. 属性1:
  23. <input type="button" class="sku" attr_id="10" value="10"/>
  24. </div>

  25. <div>
  26. 属性2:
  27. <input type="button" class="sku" attr_id="20" value="20"/>
  28. <input type="button" class="sku" attr_id="21" value="21"/>
  29. <input type="button" class="sku" attr_id="22" value="22"/>
  30. <input type="button" class="sku" attr_id="23" value="23"/>
  31. <input type="button" class="sku" attr_id="24" value="24"/>
  32. </div>

  33. <div>
  34. 属性3:
  35. <input type="button" class="sku" attr_id="30" value="30"/>
  36. <input type="button" class="sku" attr_id="31" value="31"/>
  37. <input type="button" class="sku" attr_id="32" value="32"/>
  38. <input type="button" class="sku" attr_id="33" value="33"/>
  39. <input type="button" class="sku" attr_id="34" value="34"/>
  40. <input type="button" class="sku" attr_id="35" value="35"/>
  41. <input type="button" class="sku" attr_id="36" value="36"/>
  42. <input type="button" class="sku" attr_id="37" value="37"/>
  43. <input type="button" class="sku" attr_id="38" value="38"/>
  44. </div>

  45. <div>
  46. 属性4:
  47. <input type="button" class="sku" attr_id="40" value="40"/>
  48. </div>

  49. <span id="init_time">init sku time: </span> <br />
  50. <span id="price">--</span> <br />
  51. <script type="text/javascript" src="http://libs.baidu.com/jquery/1.11.1/jquery.min.js"></script>
  52. <script type='text/javascript'>//<![CDATA[
  53. $(window).load(function(){
  54. var startTime = new Date().getTime();
  55. //属性集
  56. var keys = [
  57.         ['10'],
  58.         ['20','21','22','23','24'],
  59.         ['30','31','32','33','34','35','36','37','38'],
  60.         ['40']
  61.         ];
  62.          
  63. //后台读取结果集
  64. var data = {
  65.     "10;24;31;40": {
  66.         price:366,
  67.         count:46
  68.     },
  69.     "10;24;32;40": {
  70.         price:406,
  71.         count:66
  72.     },
  73.     "10;24;33;40": {
  74.         price:416,
  75.         count:77
  76.     },
  77.     "10;24;34;40": {
  78.         price:456,
  79.         count:9
  80.     },
  81.     "10;24;35;40": {
  82.         price:371,
  83.         count:33
  84.     },
  85.     "10;24;36;40": {
  86.         price:411,
  87.         count:79
  88.     },
  89.     "10;24;37;40": {
  90.         price:421,
  91.         count:87
  92.     },
  93.     "10;24;38;40": {
  94.         price:461,
  95.         count:9
  96.     },
  97.     "10;24;30;40": {
  98.         price:356,
  99.         count:59
  100.     },
  101.     "10;23;31;40": {
  102.         price:366,
  103.         count:50
  104.     },
  105.     "10;23;32;40": {
  106.         price:406,
  107.         count:9
  108.     },
  109.     "10;23;33;40": {
  110.         price:416,
  111.         count:90
  112.     },
  113.     "10;23;34;40": {
  114.         price:456,
  115.         count:10
  116.     },
  117.     "10;23;35;40": {
  118.         price:371,
  119.         count:79
  120.     },
  121.     "10;23;36;40": {
  122.         price:411,
  123.         count:90
  124.     },
  125.     "10;23;37;40": {
  126.         price:421,
  127.         count:10
  128.     },
  129.     "10;23;38;40": {
  130.         price:461,
  131.         count:9
  132.     },
  133.     "10;23;30;40": {
  134.         price:356,
  135.         count:46
  136.     },
  137.     "10;22;31;40": {
  138.         price:356,
  139.         count:27
  140.     },
  141.     "10;22;32;40": {
  142.         price:396,
  143.         count:38
  144.     },
  145.     "10;22;33;40": {
  146.         price:406,
  147.         count:42
  148.     },
  149.     "10;22;34;40": {
  150.         price:446,
  151.         count:50
  152.     },
  153.     "10;22;35;40": {
  154.         price:361,
  155.         count:25
  156.     },
  157.     "10;22;36;40": {
  158.         price:401,
  159.         count:40
  160.     },
  161.     "10;22;37;40": {
  162.         price:411,
  163.         count:43
  164.     },
  165.     "10;22;38;40": {
  166.         price:451,
  167.         count:42
  168.     },
  169.     "10;21;31;40": {
  170.         price:366,
  171.         count:79
  172.     },
  173.     "10;21;32;40": {
  174.         price:406,
  175.         count:79
  176.     },
  177.     "10;21;33;40": {
  178.         price:416,
  179.         count:10
  180.     },
  181.     "10;21;34;40": {
  182.         price:456,
  183.         count:10
  184.     },
  185.     "10;21;35;40": {
  186.         price:371,
  187.         count:87
  188.     },
  189.     "10;21;36;40": {
  190.         price:411,
  191.         count:10
  192.     },
  193.     "10;21;37;40": {
  194.         price:421,
  195.         count:10
  196.     },
  197.     "10;21;38;40": {
  198.         price:461,
  199.         count:80
  200.     },
  201.     "10;21;30;40": {
  202.         price:356,
  203.         count:43
  204.     },
  205.     "10;20;31;40": {
  206.         price:356,
  207.         count:46
  208.     },
  209.     "10;20;32;40": {
  210.         price:396,
  211.         count:49
  212.     },
  213.     "10;20;33;40": {
  214.         price:406,
  215.         count:65
  216.     },
  217.     "10;20;34;40": {
  218.         price:446,
  219.         count:10
  220.     },
  221.     "10;20;35;40": {
  222.         price:361,
  223.         count:34
  224.     },
  225.     "10;20;36;40": {
  226.         price:401,
  227.         count:41
  228.     },
  229.     "10;20;37;40": {
  230.         price:411,
  231.         count:36
  232.     },
  233.     "10;20;38;40": {
  234.         price:451,
  235.         count:42
  236.     },
  237.     "10;20;30;40": {
  238.         price:346,
  239.         count: 3
  240.     }
  241. }
  242. //保存最后的组合结果信息
  243. var SKUResult = {};
  244. //获得对象的key
  245. function getObjKeys(obj) {
  246.     if (obj !== Object(obj)) throw new TypeError('Invalid object');
  247.     var keys = [];
  248.     for (var key in obj)
  249.         if (Object.prototype.hasOwnProperty.call(obj, key))
  250.             keys[keys.length] = key;
  251.     return keys;
  252. }

  253. //把组合的key放入结果集SKUResult
  254. function add2SKUResult(combArrItem, sku) {
  255.     var key = combArrItem.join(";");
  256.     if(SKUResult[key]) {//SKU信息key属性·
  257.         SKUResult[key].count += sku.count;
  258.         SKUResult[key].prices.push(sku.price);
  259.     } else {
  260.         SKUResult[key] = {
  261.             count : sku.count,
  262.             prices : [sku.price]
  263.         };
  264.     }
  265. }

  266. //初始化得到结果集
  267. function initSKU() {
  268.     var i, j, skuKeys = getObjKeys(data);
  269.     for(i = 0; i < skuKeys.length; i++) {
  270.         var skuKey = skuKeys[i];//一条SKU信息key
  271.         var sku = data[skuKey]; //一条SKU信息value
  272.         var skuKeyAttrs = skuKey.split(";"); //SKU信息key属性值数组
  273.         var len = skuKeyAttrs.length;


  274.         //对每个SKU信息key属性值进行拆分组合
  275.         var combArr = arrayCombine(skuKeyAttrs);
  276.         for(j = 0; j < combArr.length; j++) {
  277.             add2SKUResult(combArr[j], sku);
  278.         }

  279.         //结果集接放入SKUResult
  280.         SKUResult[skuKey] = {
  281.             count:sku.count,
  282.             prices:[sku.price]
  283.         }
  284.     }
  285. }

  286. /**
  287. * 从数组中生成指定长度的组合
  288. */
  289. function arrayCombine(targetArr) {
  290.     if(!targetArr || !targetArr.length) {
  291.         return [];
  292.     }

  293.     var len = targetArr.length;
  294.     var resultArrs = [];

  295.     // 所有组合
  296.     for(var n = 1; n < len; n++) {
  297.         var flagArrs = getFlagArrs(len, n);
  298.         while(flagArrs.length) {
  299.             var flagArr = flagArrs.shift();
  300.             var combArr = [];
  301.             for(var i = 0; i < len; i++) {
  302.                 flagArr[i] && combArr.push(targetArr[i]);
  303.             }
  304.             resultArrs.push(combArr);
  305.         }
  306.     }
  307.    
  308.     return resultArrs;
  309. }


  310. /**
  311. * 获得从m中取n的所有组合
  312. */
  313. function getFlagArrs(m, n) {
  314.     if(!n || n < 1) {
  315.         return [];
  316.     }

  317.     var resultArrs = [],
  318.         flagArr = [],
  319.         isEnd = false,
  320.         i, j, leftCnt;

  321.     for (i = 0; i < m; i++) {
  322.         flagArr[i] = i < n ? 1 : 0;
  323.     }

  324.     resultArrs.push(flagArr.concat());

  325.     while (!isEnd) {
  326.         leftCnt = 0;
  327.         for (i = 0; i < m - 1; i++) {
  328.             if (flagArr[i] == 1 && flagArr[i+1] == 0) {
  329.                 for(j = 0; j < i; j++) {
  330.                     flagArr[j] = j < leftCnt ? 1 : 0;
  331.                 }
  332.                 flagArr[i] = 0;
  333.                 flagArr[i+1] = 1;
  334.                 var aTmp = flagArr.concat();
  335.                 resultArrs.push(aTmp);
  336.                 if(aTmp.slice(-n).join("").indexOf('0') == -1) {
  337.                     isEnd = true;
  338.                 }
  339.                 break;
  340.             }
  341.             flagArr[i] == 1 && leftCnt++;
  342.         }
  343.     }
  344.     return resultArrs;
  345. }


  346. //初始化用户选择事件
  347. $(function() {
  348.     initSKU();
  349.     var endTime = new Date().getTime();
  350.     $('#init_time').text('init sku time: ' + (endTime - startTime) + " ms");
  351.     $('.sku').each(function() {
  352.         var self = $(this);
  353.         var attr_id = self.attr('attr_id');
  354.         if(!SKUResult[attr_id]) {
  355.             self.attr('disabled', 'disabled');
  356.         }
  357.     }).click(function() {
  358.         var self = $(this);

  359.         //选中自己,兄弟节点取消选中
  360.         self.toggleClass('bh-sku-selected').siblings().removeClass('bh-sku-selected');
  361.         
  362.         //已经选择的节点
  363.         var selectedObjs = $('.bh-sku-selected');

  364.         if(selectedObjs.length) {
  365.             //获得组合key价格
  366.             var selectedIds = [];
  367.             selectedObjs.each(function() {
  368.                 selectedIds.push($(this).attr('attr_id'));
  369.             });
  370.             selectedIds.sort(function(value1, value2) {
  371.                 return parseInt(value1) - parseInt(value2);
  372.             });
  373.             var len = selectedIds.length;
  374.             var prices = SKUResult[selectedIds.join(';')].prices;
  375.             var maxPrice = Math.max.apply(Math, prices);
  376.             var minPrice = Math.min.apply(Math, prices);
  377.             $('#price').text(maxPrice > minPrice ? minPrice + "-" + maxPrice : maxPrice);
  378.             
  379.             //用已选中的节点验证待测试节点 underTestObjs
  380.             $(".sku").not(selectedObjs).not(self).each(function() {
  381.                 var siblingsSelectedObj = $(this).siblings('.bh-sku-selected');
  382.                 var testAttrIds = [];//从选中节点中去掉选中的兄弟节点
  383.                 if(siblingsSelectedObj.length) {
  384.                     var siblingsSelectedObjId = siblingsSelectedObj.attr('attr_id');
  385.                     for(var i = 0; i < len; i++) {
  386.                         (selectedIds[i] != siblingsSelectedObjId) && testAttrIds.push(selectedIds[i]);
  387.                     }
  388.                 } else {
  389.                     testAttrIds = selectedIds.concat();
  390.                 }
  391.                 testAttrIds = testAttrIds.concat($(this).attr('attr_id'));
  392.                 testAttrIds.sort(function(value1, value2) {
  393.                     return parseInt(value1) - parseInt(value2);
  394.                 });
  395.                 if(!SKUResult[testAttrIds.join(';')]) {
  396.                     $(this).attr('disabled', 'disabled').removeClass('bh-sku-selected');
  397.                 } else {
  398.                     $(this).removeAttr('disabled');
  399.                 }
  400.             });
  401.         } else {
  402.             //设置默认价格
  403.             $('#price').text('--');
  404.             //设置属性状态
  405.             $('.sku').each(function() {
  406.                 SKUResult[$(this).attr('attr_id')] ? $(this).removeAttr('disabled') : $(this).attr('disabled', 'disabled').removeClass('bh-sku-selected');
  407.             })
  408.         }
  409.     });
  410. });
  411. });//]]>

  412. </script>
  413. </body>
  414. </html>
复制代码

相关帖子

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|PHPIN.NET ( 冀ICP备00000001号 )|网站地图  

GMT+8, 2016-12-10 20:40

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表