[23→100]SKU组合查询算法

问题场景

SKU最小存货单位(Stock Keeping Unit)在连锁零售门店中有时称单品为一个SKU,定义为保存库存控制的最小可用单位,例如纺织品中一个SKU通常表示规格、颜色、款式。

逛过淘宝的人都知道一种商品可能有多种属性类型,拿一件衣服来说,

  • 性别:男、女
  • 颜色:红、绿、蓝
  • 尺寸上:38、39、40
  1. 只有3个属性全部都选定的时候,才能真正确定你买的是哪一件衣服,也才能知道衣服对应的价格、库存等信息。

  2. 如果你只选择了其中1或2个属性,剩下未被选择的属性要进行判断,确定哪些属性值可以被选中,哪些不能(因为有些sku组合不存在,或者库存为0,无法购买)

核心问题

  1. 如何根据全部属性查询对应的价格、库存?
  2. 如何确定哪些属性值可以被选中,哪些不能?

前者很简单,遍历一遍所有的SKU信息列表就知道了,或者利用Map直接获取就行。后者比较麻烦,需要进行多次匹配。大体思想如下:

  1. 遍历SKU列表,从中选出包含已选中属性和属性值的条目列表containTargetList;
  2. 遍历containTargetList,找出存在其中的未被选中属性的属性值
  3. 结合未被选中属性的全部属性值未被选中属性在containTargetList中存在的属性值,确定未被选中属性中哪些属性值是不能被选中的。

附录:Python的简易实现版

#!/usr/bin/python
# -*- coding: utf-8 -*-
#################################
## 输入:连续点击事件
## 输出:各个按钮的状态
#################################

# 不同的规格属性
KEYS = {
"size":["38", "39", "40"],
"color":["red", "blue", "green"],
"sex":["man", "woman"],
};

# 不同的规格属性组合对应的 库存和价格
SKUS = {
"39;red;man":{"price":100, "count":10},
"40;red;man":{"price":100, "count":10},
"38;grean;woman":{"price":100, "count":20},
"39;red;woman":{"price":100, "count":30},
"39;blue;man":{"price":100, "count":10},
"40;blue;man":{"price":100, "count":10},
"38;blue;woman":{"price":100, "count":20},
"39;green;woman":{"price":100, "count":30},
}


def processSku(inputData):
    ## 1. 预处理数据,将规格的属性值变为对象的属性值,便于读取比较
    for sku in SKUS:
        array = sku.split(";");
        SKUS[sku]["size"] = array[0]
        SKUS[sku]["color"] = array[1]
        SKUS[sku]["sex"] = array[2]
    ## 2. 找出被选中的属性值列表
    inputDataArray = inputData.split(";");
    targetedDict = {}
    for data in inputDataArray:
        if ":" in data:
            [key, value] = data.split(":")
            targetedDict[key] = value
    print "已经选中的属性:" , targetedDict
    if(len(targetedDict) == len(KEYS)):
        key = "%s;%s;%s" % (targetedDict["size"],targetedDict["color"],targetedDict["sex"])
        if key in SKUS:
            print "所有属性皆被选中,对应的结果为\n" , key , ":", SKUS[key]
        else:
            print "所有属性皆被选中,但查无结果\n"
        return;
    ## 3. 找出未被选中的属性值列表
    unTargetDict = {}
    for key in KEYS:
        if key not in targetedDict:
            unTargetDict[key] = KEYS[key]
    print "未被选中的属性:" , unTargetDict
    ## 4. 判断未被选中的属性值是否能被选中
    ### 4.1. 遍历规格属性组合,找到包含`targetedDict属性值`的所有sku组合
    containTargetList = []
    for skuItem in SKUS:
        canAppend = True
        for key in targetedDict:
            if SKUS[skuItem][key] != targetedDict[key]:
                canAppend = False
                break;
        if canAppend:
            containTargetList.append(SKUS[skuItem])
    print "包含选中属性的sku条目:"
    for skuItem in containTargetList:
        print skuItem

    ### 4.2 判断每个属性下面每个属性值的存在状态,True表示可以选中,False表示不能继续选择了
    skuStaus = {}
    for skuKey in unTargetDict:
        skuStaus[skuKey] = {}
        for skuValue in unTargetDict[skuKey]:
            skuStaus[skuKey][skuValue] = False;

    for skuItem in containTargetList:
        for skuKey in unTargetDict:
            for skuValue in unTargetDict[skuKey]:
                if skuItem[skuKey] ==  skuValue:
                    skuStaus[skuKey][skuValue] = True;
                    break;

    print "\n可继续选中的属性值状态为: "
    for skuKey in skuStaus:
        print skuKey,":",skuStaus[skuKey]

### 测试数据
inputDatas =[
# "size:39",
"size:40;",
# "size:39;sex:woman", #选中size 39和sex:woman
# "size:39;sex:woman;color:red",
# "size:39;sex:woman;color:red1",
]

for inputData in inputDatas:
    print "\n\n------Start:测试数据为%s------" % inputData
    processSku(inputData)
    print "------end----------------\n\n"

优化建议:

  1. 如果用户下一次选中的属性值,没有影响之前的属性值选择。也就是说,用户上一次选中了“男”这个属性值,这一次选中了“40”这个属性值,可以直接在上一次containTargetList的基础上继续过滤,而不用遍历全部的SKU列表。

Panda

2016-05-19

参考:

  1. Fan同学提供的算法概要
  2. 淘宝SKU组合查询算法实现
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,860评论 18 139
  • 工厂模式类似于现实生活中的工厂可以产生大量相似的商品,去做同样的事情,实现同样的效果;这时候需要使用工厂模式。简单...
    舟渔行舟阅读 7,827评论 2 17
  • 1、窗体 1、常用属性 (1)Name属性:用来获取或设置窗体的名称,在应用程序中可通过Name属性来引用窗体。 ...
    Moment__格调阅读 4,589评论 0 11
  • 文/狗乖乖 拿秒回来说事的人,一定是个理想大虾。 工作和生活中,我是个比较典型的健忘症者。每凡遇到开会,会前我都会...
    薛静春阅读 232评论 10 11
  • 1. 有一次和周其仁教授聊天,我请教他一个问题:这么多年来,经常看见您出门演讲,但是从来不见您上电视,同样是传播思...
    雨露姐阅读 193评论 0 0