前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >猿实战20——商品发布之sku与笛卡尔乘积的那些事儿

猿实战20——商品发布之sku与笛卡尔乘积的那些事儿

作者头像
山旮旯的胖子
发布2020-10-22 11:03:39
7200
发布2020-10-22 11:03:39
举报
文章被收录于专栏:猿人工厂猿人工厂

猿实战是一个原创系列文章,通过实战的方式,采用前后端分离的技术结合SpringMVC Spring Mybatis,手把手教你撸一个完整的电商系统,变身猿人找到工作不是问题。还等什么呢?关注公号,取基础代码,一起实战吧。

上两个章节,猿人君教会了你如何选择类目,以及加载商品发布需要准备的数据,今天,猿人君会教授你商品发布中的一个核心知识,sku数据生成。

功能概览

在商品发布详情页面,勾选销售属性下的销售属性值后,页面会根据选择的销售属性值,动态生成需要详细填写信息的sku数据。事实上,商品是对sku的一个聚合,我们真正售卖的东西,是sku。关于商品和sku的区别,大家可以看之前的设计文章。

数据库设计

本章节主要讲述内容,在于sku数据生成以及页面数据处理问题,稍微偏算法一些,不涉及数据库相关内容。

前端功能实现

勾选销售属性值,生成需要填写的sku列表功能实现。

勾选销售属性值后,页面生成需要填写的sku列表。在上一章节,我们已经为此做好了数据准备,我们先回顾下,销售属性的获取功能。

从功能上来讲,当我们勾选一个销售属性时,那么就会生成条相应的记录。比如,某个商品有两个销售属性——容量和颜色。其中容量有2G和4G两个属性值,颜色可能有多种,比如,红,黄,蓝三种颜色。那么当我们勾选将这些属性值勾选之后,页面会生成2G,红色;2G,黄色;2G,蓝色;4G,红色;4G,黄色;4G,蓝色。这么六种sku。以此类推,要是有更多的销售属性和属性值,那么就会产生更多的sku了。

嗯,这似乎是一个比较头疼的问题,需要将勾选的销售属性值,进行一一组合。简单点来讲,就选中的属性和属性值而言,对应的sku组合,是一个笛卡尔积组合可能性的问题。

这个问题的痛点在于不知道勾选了哪些销售属性和属性值,从而导致循环的不确定性,为了简化问题,我们先假设全量输出这些可能性,我们可以先用java来模拟这一段算法。我们考虑,有销售属性aa,bb,cc,dd。aa分别有a1,a2两个属性值,bb只有1个属性值b1,cc有属性值c1,c2,c3,dd有属性值d1,d2。

如果全部勾选的话,我们得到组合值将类似于这样的情况:a1,b1,c1,d2;a1,b1,c1,d1这样的组合。我们先定义代表属性和属性值的数组。

代码语言:javascript
复制
    private static String[] aa={"a1","a2"};
    private static String[] bb={"b1"};
    private static String[] cc={"c1","c2","c3"};
    private static String[] dd={"d1","d2"};

再对比我们所需要的组合结果,你会发现我们要的值类似于如下下标aa[0],bb[0],cc[0],dd[1];aa[0],bb[0],cc[0],dd[0]……,也就是说,要完成a1的说有组合可能性,需要遍历bb,cc,dd的每一个下标来完成这个过程。

为了方便组合,我们可以将上述的结构看成一个二维数组。

代码语言:javascript
复制
private static String[][] xyz={aa,bb,cc,dd};

想要获取每一个值的组合,我们分别根据下标遍历每一个数组就好了,但是在循环遍历的过程中,我们需要事先知晓当前的数组,已经遍历到哪一个位置了,否则会导致数组越界。为了解决这一个问题,我我们定义一个数组。

代码语言:javascript
复制
 private static int[] counter={0,0,0,0};

用于记录二维数组中,每一个数组遍历到的次数。

除此之外我们怎样才能保证,二维数组中的每一个数组元素中的元素都被遍历到呢?这个就需要用到递归了。

代码语言:javascript
复制
private static void handleCounterIndex(){
        counter[counterIndex]++;
        if (counter[counterIndex]>=xyz[counterIndex].length){
            counter[counterIndex]=0;
            counterIndex--;
            if (counterIndex>=0){
                handleCounterIndex();
            }
            counterIndex=xyz.length-1;
        }
}

那会产生多少种结果呢?自然是所有属性值的乘积了。我们可以看下完整的java程序:

代码语言:javascript
复制
public class Test {
    private static String[] aa={"a1","a2"};
    private static String[] bb={"b1"};
    private static String[] cc={"c1","c2","c3"};
    private static String[] dd={"d1","d2"};
    private static String[][] xyz={aa,bb,cc,dd};
    private static int counterIndex =xyz.length-1;
    private static int[] counter={0,0,0,0};

    public static void main(String[] args) {
        int myLength=aa.length*bb.length*cc.length*dd.length;
        for (int i=0;i<myLength;i++){
            System.out.print(aa[counter[0]]);
            System.out.print("\t");
            System.out.print(bb[counter[1]]);
            System.out.print("\t");
            System.out.print(cc[counter[2]]);
            System.out.print("\t");
            System.out.print(dd[counter[3]]);
            System.out.println();
            handleCounterIndex();
        }
}

private static void handleCounterIndex(){
        counter[counterIndex]++;
        if (counter[counterIndex]>=xyz[counterIndex].length){
            counter[counterIndex]=0;
            counterIndex--;
            if (counterIndex>=0){
                handleCounterIndex();
            }
            counterIndex=xyz.length-1;
        }
    }

}

嗯,以上只是固定的长度的写法,有这个基础了,我们将java程序转变为需要为我们需要的JavaScript程序就好了。

代码语言:javascript
复制
// 销售属性选择改变
    checksaleBoxClick(value) {
      // console.log('执行了')
      this.ruleForm.tableList = []
      // 默认都未勾选
      this.initSelectValues()
      for (let i = 0; i < value.length; i++) {
        // 选中选项
        this.selectValues(value[i])
      }
      // console.log(this.saleCheckedList)
      // 初始化需要做笛卡尔集的选项
      var spos = []
      for (let i = 0; i < this.salePropertyList.length; i++) {
        if (this.salePropertyList[i].checked === 1) {
          var svalues = []
          for (let j = 0; j < this.salePropertyList[i].valueList.length; j++) {
            if (this.salePropertyList[i].valueList[j].checked === 1) {
              var obj = {
                id: this.salePropertyList[i].valueList[j].id,
                name: this.salePropertyList[i].valueList[j].name
              }
              svalues.push(obj)
            }
          }
          var obj2 = {
            id: this.salePropertyList[i].id,
            name: this.salePropertyList[i].name,
            valueList: []
          }
          obj2.valueList = svalues
          spos.push(obj2)
        }
      }
      // 勾选属性小于1表示未选中
      if (spos.length < 1) {
        return
      }
      var counterIndex = spos.length - 1
      var mylength = 1
      var counter = []
      for (let i = 0; i < spos.length; i++) {
        counter.push(0)
        mylength *= spos[i].valueList.length
      }
      for (let k = 0; k < mylength; k++) {
        var str = ''
        var valueList = []
        for (let i = 0; i < spos.length; i++) {
          if (undefined !== spos[i].valueList[counter[i]]) {
            str = str + spos[i].name + ':' + spos[i].valueList[counter[i]].name + '\t'
            var valueObj = {
              propertyId: spos[i].id,
              propertyValueId: spos[i].valueList[counter[i]].id
            }
            valueList.push(valueObj)
          }
        }
 
        this.initTableRow(str, valueList)
        // 处理行记录
        this.handle(counter, spos, counterIndex)
        console.log(str)
      }
    },
    // 每一个值和其它值组合
    initTableRow(proValueName, proValues) {
      var skuObj = {
        proValues: proValues,
        propertyValue: proValueName,
        skuName: '',
        supplyPrice: null,
        // 卖家SKU编码
        skuCode: '',
        costPrice: null,
        skuFileList: [],
        imgList: []
      }
      this.ruleForm.tableList.push(skuObj)
    },
    handle(counter, dataList, counterIndex) {
      counter[counterIndex]++
      // counter和列数比较
      if (counter[counterIndex] >= dataList[counterIndex].valueList.length) {
        counter[counterIndex] = 0
        counterIndex--
        if (counterIndex >= 0) {
          this.handle(counter, dataList, counterIndex)
        }
        counterIndex = dataList.length - 1
      }
    }
 

 
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 猿人工厂 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档