没给大家介绍正文之前先给大家补充点知识:
js笛卡尔积算法
根据给的对象或者数组生成笛卡尔积
//笛卡儿积组合 function descartes(list) { //parent上一级索引;count指针计数 var point = {}; var result = []; var pIndex = null; var tempCount = 0; var temp = []; //根据参数列生成指针对象 for(var index in list) { if(typeof list[index] == 'object') { point[index] = {'parent':pIndex,'count':0} pIndex = index; } } //单维度数据结构直接返回 if(pIndex == null) { return list; } //动态生成笛卡尔积 while(true) { for(var index in list) { tempCount = point[index]['count']; temp.push(list[index][tempCount]); } //压入结果数组 result.push(temp); temp = []; //检查指针最大值问题 while(true) { if(point[index]['count']+1 >= list[index].length) { point[index]['count'] = 0; pIndex = point[index]['parent']; if(pIndex == null) { return result; } //赋值parent进行再次检查 index = pIndex; } else { point[index]['count']++; break; } } } }
好了,关于js笛卡尔积算法只是给下文做个铺垫,不多说了,言归正传。
一、需求描述
电商网站的商品发布功能,类似京东的商品详细页,如下图,这样的可选择功能,在后台是如何生成的呢,其实你看到的一个iphone6在发布时并不只是发布一个商品,而是很多个,因为每一个选择出来的iphone6价格是不一样的,那么发布商品时这些可选择项又是从一堆属性和属性值中挑选出来的,问题来了,发布时挑选的属性个数是不一样的,属性值也是不一样的,那么生成的商品个数是根据属性和属性值组合出来的。
二、直接上代码
<script> /** * 商品属性类型 * 一个属性个数是不确定的 */ var Spec = function(specName,specItems){ this.specName = specName; //属性名称 this.specItems = specItems;//数值值,是个数组,数组个数不确定 } var result = [];//组合成产品集 /** * 发布一款商品选择的一个属性,这是一个规格数组,数组个数不确定 * 根据这个选择的属性组合成不同的产品 */ var selectSpec = [{specName:'容量',specItems:['16G','64G','128G']}, {specName:'颜色',specItems:['土豪金','银色','黑色','pink']}, {specName:'网络',specItems:['联通','移动','电信']}]; function combine(index, current){ if (index < selectSpec.length - 1){ var specItem = selectSpec[index]; var keya = specItem.specName; var items = specItem.specItems; if(items.length==0){ run( index + 1, current); } for (var i = 0; i < items.length; i++){ if(!items[i])continue; var newMap = {}; newMap = $.extend(newMap,current); newMap[keya] = items[i]; run( index + 1, newMap); } }else if (index == selectSpec.length - 1){ var specItem = selectSpec[index]; var keya = specItem.specName; var items = specItem.specItems; if(items.length==0){ result.push(current); } for (var i = 0; i < items.length; i++){ if(!items[i])continue; var newMap = {}; newMap = $.extend(newMap,current); newMap[keya] = items[i]; result.push(newMap); } } } combine(0, {}); console.info(result); /**组合成产品集 * [Object { 容量="16G", 颜色="土豪金", 网络="联通"}, * Object { 容量="16G", 颜色="土豪金", 网络="移动"}, * Object { 容量="16G", 颜色="土豪金", 网络="电信"}, * Object { 容量="16G", 颜色="银色", 网络="联通"}, * Object { 容量="16G", 颜色="银色", 网络="移动"}, * Object { 容量="16G", 颜色="银色", 网络="电信"}, * Object { 容量="16G", 颜色="黑色", 网络="联通"}, * Object { 容量="16G", 颜色="黑色", 网络="移动"}, * Object { 容量="16G", 颜色="黑色", 网络="电信"}, * Object { 容量="16G", 颜色="pink", 网络="联通"}, * Object { 容量="16G", 颜色="pink", 网络="移动"}, * Object { 容量="16G", 颜色="pink", 网络="电信"}, * Object { 容量="64G", 颜色="土豪金", 网络="联通"}, * Object { 容量="64G", 颜色="土豪金", 网络="移动"}, * Object { 容量="64G", 颜色="土豪金", 网络="电信"}, * Object { 容量="64G", 颜色="银色", 网络="联通"}, * Object { 容量="64G", 颜色="银色", 网络="移动"}, * Object { 容量="64G", 颜色="银色", 网络="电信"}, * Object { 容量="64G", 颜色="黑色", 网络="联通"}, * Object { 容量="64G", 颜色="黑色", 网络="移动"}, * Object { 容量="64G", 颜色="黑色", 网络="电信"}, * Object { 容量="64G", 颜色="pink", 网络="联通"}, * Object { 容量="64G", 颜色="pink", 网络="移动"}, * Object { 容量="64G", 颜色="pink", 网络="电信"}, * Object { 容量="128G", 颜色="土豪金", 网络="联通"}, * Object { 容量="128G", 颜色="土豪金", 网络="移动"}, * Object { 容量="128G", 颜色="土豪金", 网络="电信"}, * Object { 容量="128G", 颜色="银色", 网络="联通"}, * Object { 容量="128G", 颜色="银色", 网络="移动"}, * Object { 容量="128G", 颜色="银色", 网络="电信"}, * Object { 容量="128G", 颜色="黑色", 网络="联通"}, * Object { 容量="128G", 颜色="黑色", 网络="移动"}, * Object { 容量="128G", 颜色="黑色", 网络="电信"}, * Object { 容量="128G", 颜色="pink", 网络="联通"}, * Object { 容量="128G", 颜色="pink", 网络="移动"}, * Object { 容量="128G", 颜色="pink", 网络="电信"}] */ </script>