前言

做过电商项目前端售卖的应该都遇见过不同规格产品库存的计算问题,业界名词叫做sku(stock Keeping Unit),库存量单元对应我们售卖的具体规格,比如一部手机具体型号规格,其中iphone6s 4G 红色就是一个sku。这里我们区别spu(Standard Product Unit),标准化产品单元,比如一部手机型号iphone6s就是一个spu

sku 算法

在前端展示商品时,根据用户选择的不同sku,我们需要计算出不同的库存量动态展示给用户,这里就衍生出了sku算法。

数据结构

我们先看看在后端服务器保存库存的数据结构一般是长怎么样的:

// 库存列表
const skuList = [
{
skuId: '0',
skuGroup: ['红色', '大'],
remainStock: 7,
price: 2,
picUrl: 'https://dummyimage.com/100x100/ff00b4/ffffff&text=大'
},
{
skuId: '1',
skuGroup: ['红色', '小'],
remainStock: 3,
price: 4,
picUrl: 'https://dummyimage.com/100x100/ff00b4/ffffff&text=小'
},
{
skuId: '2',
skuGroup: ['蓝色', '大'],
remainStock: 0,
price: 0.01,
picUrl: 'https://dummyimage.com/100x100/0084ff/ffffff&text=大'
},
{
skuId: '3',
skuGroup: ['蓝色', '小'],
remainStock: 1,
price: 1,
picUrl: 'https://dummyimage.com/100x100/0084ff/ffffff&text=小'
}
]; // 规格列表
const skuNameList = [
{
skuName: "颜色",
skuValues: ["红色", "蓝色"]
},
{
skuName: "尺寸",
skuValues: ["大", "小"]
}
];

算法演示

在前端用户选择单个规格或多个规格后,我们需要动态计算出此时其他按钮是否还能点击(组合有库存),以及当前状态对应的总库存量,封面图和价格区间。

以上面的数据举个

开始时什么都没有选择,展示默认图片,规格列表中的第一项组合(['红色-大'])对应的图片,库存为商品总库存,价格为商品的价格区间。然后在用户选择某个属性或几个属性的时候实时计算对应的图片,库存,价格区间。

同时根据当前已选属性,置灰不可选择的属性。在本例中,蓝色 大的产品对应的库存为 0,所以当我们选择其中一项 蓝色 或者 大 的时候,需要置灰另一个属性选项。

实现思路-第一种算法

为了大家能看清下面的分析,在此定义下相关名词,库存列表:skuList,规格列表:skuNameList,属性:skuNameList-skuValues数组下的单个元素,规格:skuNameList下的单个元素

sku 算法的难点在于如何根据当前已选属性(未选,选择部分,全选)来判断当前其它属性是否可选

在网上查找相关算法时比较广泛流传的是来自淘宝前端的两种算法,下面将实现第一种算法:

主要思路就是遍历当前的规格列表下的属性,根据已选属性及库存列表判断当前属性按钮是否有库存(可选):

  • 将规格列表下的已选属性集合作为入参 selected,如果在当前规格未选择相关属性则传入空字符串,即最开始时 selected === ['', '']

  • 初始化相关变量,库存,价格区间,图片,及属性对象attrState(attrState 用于标记每个属性是否可选)

  • 遍历规格列表,移除存在与当前规格属性数组中已选属性(假设当前规格未选择)

  • 遍历规格属性,依次将当前属性和已选属性组合

  • 将上步的组合作为最终属性组合,遍历库存列表是否存在库存(属于子集关系且库存>0),有库存则标记可选(true)

  • 最后再次遍历库存列表,用来获取当前库存,图片,价格等 sku 数据

/**
* 获取sku信息
* @param {Array} selected 已选属性数组
* @return {Object} skuInfo
*
*/
const getSkuInfo = (selected) => {
// 用以记录每个按钮状态的,例如 itemState['红色'] = true 表示高亮
const attrState = {};
let picUrl = '';
let minPrice = Number.MAX_VALUE;
let maxPrice = 0;
let remainStock = 0; // in array not in others
const difference = (array, others) => {
return array.filter((item) => others.indexOf(item) === -1);
}; // every in array in others
const isSubset = (array, others) => {
return array.every((item) => others.indexOf(item) > -1);
}; // 遍历规格列表
skuNameList.forEach((spec) => {
// 移除当前遍历规格下的已选属性
const tempSelected = difference(selected, spec.skuValues).filter(name => name); // 遍历规格属性
spec.skuValues.forEach((name) => {
const willSelected = [...tempSelected, name]; // 默认无库存不可选
attrState[name] = false; // 在库存列表寻找匹配库存
for (let i = 0, len = skuList.length; i < len; i++) {
const skuGroup = skuList[i].skuGroup; if (isSubset(willSelected, skuGroup) && skuList[i].remainStock) {
attrState[name] = true;
break;
}
}
});
}); // 实际已选属性,过滤空字符串
const realSelected = selected.filter((item) => item); // 默认选择用于匹配当前图片
const defaultSelected = selected.map(
(name, idx) => name || skuNameList[idx].skuValues[0]
); skuList.forEach((sku) => {
if (isSubset(realSelected, sku.skuGroup)) {
remainStock += sku.remainStock;
maxPrice = maxPrice > sku.price ? maxPrice : sku.price;
minPrice = minPrice < sku.price ? minPrice : sku.price; // 取当前图片
if (isSubset(defaultSelected, sku.skuGroup)) {
picUrl = sku.picUrl;
}
}
}); return {
attrState,
picUrl,
minPrice,
maxPrice,
remainStock,
};
};

总结

做过电商项目的应该都处理或者听说过sku,学习相关概念和真正理解如何计算sku可以帮助我们更加熟悉业务,提升自己对于相关业务的处理能力。以后在面试中遇到面试官的提问也能更稳一些。后面将介绍第二种算法,其思路更容易理解,也是比较多同学在业务中采用的方式。

参考


欢迎到前端学习打卡群一起学习~516913974

sku算法介绍及实现的更多相关文章

  1. 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍

    考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...

  2. KNN算法介绍

    KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...

  3. ISP基本框架及算法介绍

    什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...

  4. Python之常见算法介绍

    一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...

  5. RETE算法介绍

    RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...

  6. H2O中的随机森林算法介绍及其项目实战(python实现)

    H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...

  7. STL 算法介绍

    STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成.        <algorithm ...

  8. Levenshtein字符串距离算法介绍

    Levenshtein字符串距离算法介绍 文/开发部 Dimmacro KMP完全匹配算法和 Levenshtein相似度匹配算法是模糊查找匹配字符串中最经典的算法,配合近期技术栏目关于算法的探讨,上 ...

  9. 机器学习概念之特征选择(Feature selection)之RFormula算法介绍

    不多说,直接上干货! RFormula算法介绍: RFormula通过R模型公式来选择列.支持R操作中的部分操作,包括‘~’, ‘.’, ‘:’, ‘+’以及‘-‘,基本操作如下: 1. ~分隔目标和 ...

随机推荐

  1. windows远程执行命令总结

    1. 利用Impacket Impacket是一个Python类库,用于对SMB1-3或IPv4 / IPv6 上的TCP.UDP.ICMP.IGMP,ARP,IPv4,IPv6,SMB,MSRPC, ...

  2. LateX的简单字体设置(颜色,居中,大小等)

    \(\color{red}{Ⅰ.文本单行居中}\) $$\text{我是蒟蒻}$$ \[\text{我是蒟蒻} \] \(\color{Black}{Ⅱ.设置字体颜色}\) $$\color{Purp ...

  3. python学习笔记-零碎知识点

    1. 绝对值 abs(-4) 结果: 4 2.

  4. D365,实现批量上传和下载文件的工具

    这里演示下批量上传文件到D365的小程序工具,下载功能也是一样的思路跟逻辑. 通过文件名的前缀跟各个主档表的主键进行绑定来决定将附件挂在哪里. 1.上传界面. 2.查看附件上传结果.

  5. 【Hadoop离线基础总结】大数据集群环境准备

    大数据集群环境准备 三台虚拟机关闭防火墙 centOS 7 service firewalld stop ->关闭防火墙 chkconfig firewalld off ->开机关闭防火墙 ...

  6. 关于网上quartus ii 生成fft核出现问题解决

    ------------恢复内容开始------------ 关于网上quartus ii 生成fft核出现问题解决 1:必须把软件破解啦 2:必须把IP核破解啦 破解步骤网上也有可以直接看,一定要全 ...

  7. Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表

    Sharding JDBC整合SpringBoot 2.x 和 MyBatis Plus 进行分库分表 交易所流水表的单表数据量已经过亿,选用Sharding-JDBC进行分库分表.MyBatis-P ...

  8. 多线程实践—Python多线程编程

    多线程实践 前面的一些文章和脚本都是只能做学习多线程的原理使用,实际上什么有用的事情也没有做.接下来进行多线程的实践,看一看在实际项目中是怎么使用多线程的. 图书排名示例 Bookrank.py: 该 ...

  9. Docker学习笔记(二):端口映射与容器互联

    端口映射 使用docker run时,可以指定-P(大写)与-p(小写)参数映射端口. docker run -P -P(大写)会随机映射一个端口到容器的内部端口 -> [feifei@ffma ...

  10. Spring Cloud Alibaba入门实战之nacos(一)

    Spring Cloud Alibaba入门实战之nacos(一) 前情介绍 ​ Spring Cloud Alibaba 是阿里巴巴提供的新一代的微服务解决方案,相信会有越来越多采用微服务架构的公司 ...