sku算法介绍及实现
前言
做过电商项目前端售卖的应该都遇见过不同规格产品库存的计算问题,业界名词叫做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算法介绍及实现的更多相关文章
- 【原创】机器学习之PageRank算法应用与C#实现(1)算法介绍
考虑到知识的复杂性,连续性,将本算法及应用分为3篇文章,请关注,将在本月逐步发表. 1.机器学习之PageRank算法应用与C#实现(1)算法介绍 2.机器学习之PageRank算法应用与C#实现(2 ...
- KNN算法介绍
KNN算法全名为k-Nearest Neighbor,就是K最近邻的意思. 算法描述 KNN是一种分类算法,其基本思想是采用测量不同特征值之间的距离方法进行分类. 算法过程如下: 1.准备样本数据集( ...
- ISP基本框架及算法介绍
什么是ISP,他的工作原理是怎样的? ISP是Image Signal Processor的缩写,全称是影像处理器.在相机成像的整个环节中,它负责接收感光元件(Sensor)的原始信号数据,可以理解为 ...
- Python之常见算法介绍
一.算法介绍 1. 算法是什么 算法是指解题方案的准确而完整的描述,是一系列解决问题的清晰指令,算法代表着用系统的方法描述解决问题的策略机制.也就是说,能够对一定规范的输入,在有限时间内获得所要求的输 ...
- RETE算法介绍
RETE算法介绍一. rete概述Rete算法是一种前向规则快速匹配算法,其匹配速度与规则数目无关.Rete是拉丁文,对应英文是net,也就是网络.Rete算法通过形成一个rete网络进行模式匹配,利 ...
- H2O中的随机森林算法介绍及其项目实战(python实现)
H2O中的随机森林算法介绍及其项目实战(python实现) 包的引入:from h2o.estimators.random_forest import H2ORandomForestEstimator ...
- STL 算法介绍
STL 算法介绍 算法概述 算法部分主要由头文件<algorithm>,<numeric>和<functional>组成. <algorithm ...
- Levenshtein字符串距离算法介绍
Levenshtein字符串距离算法介绍 文/开发部 Dimmacro KMP完全匹配算法和 Levenshtein相似度匹配算法是模糊查找匹配字符串中最经典的算法,配合近期技术栏目关于算法的探讨,上 ...
- 机器学习概念之特征选择(Feature selection)之RFormula算法介绍
不多说,直接上干货! RFormula算法介绍: RFormula通过R模型公式来选择列.支持R操作中的部分操作,包括‘~’, ‘.’, ‘:’, ‘+’以及‘-‘,基本操作如下: 1. ~分隔目标和 ...
随机推荐
- docker批量删除本地镜像和容器
长时间运行docker,每次只用docker kill去停止容器,但是从没删除过本地镜像,导致有上百个镜像在占用内存. 1.批量停止容器 docker container stop $(docker ...
- P1725 琪露诺(单调队列优化)
描述:https://www.luogu.com.cn/problem/P1725 小河可以看作一列格子依次编号为0到N,琪露诺只能从编号小的格子移动到编号大的格子.而且琪露诺按照一种特殊的方式进行移 ...
- 数位dp H - F(x) HDU - 4734
http://acm.hdu.edu.cn/showproblem.php?pid=4734 一般数位dp表示的是数的性质,这个题目也是一样,但是我们求出来的是一个函数的值,怎么把这个值转化成一类数, ...
- Spring官网阅读(八)容器的扩展点(三)(BeanPostProcessor)
在前面两篇关于容器扩展点的文章中,我们已经完成了对BeanFactoryPostProcessor很FactoryBean的学习,对于BeanFactoryPostProcessor而言,它能让我们对 ...
- gulp基本使用
一.gulp是什么 gulp强调的是前端开发的工作流程,我们可以通过定义task事件定义事件的执行顺序,gulp去执行这些事件,构建整个前端开发的工作流程 gulp常见定义事件,例如: 变更静态资源 ...
- 折腾了一晚上的“equals”和“==”
最近在仿写美团这个项目的时候,遇到了一点关于字符串比较的问题,这里记录一下,避免以后再犯. 由于之前学c语言的时候,习惯性用“==”进行比较,初识Java,不知道有什么别的方法可以进行字符串比较,于是 ...
- vue 如何实现 Input 输入框模糊查询方法
原理:原生js的indexOf() 方法,该方法将从头到尾地检索数组,看它是否含有对应的元素.开始检索的位置在数组 start 处或数组的开头(没有指定 start 参数时).如果找到一个 item, ...
- js移动端复制到剪贴板
// 复制到剪切板 function copy(str){ var save = function (e){ e.clipboardData.setData('text/plain',str);//c ...
- 放大镜功能 JS原生写法
********** 希望对大家帮助 我会继续努力的 如果有不对的地方请大家帮忙指出****** 1 [JS 代码] <script> var oBox = document.getEle ...
- css段落样式
字间距 letter-spacing 首行缩进 text-indent