今天的工作任务主要就集中在研究商品“选项”编辑功能上了,主要有两个场景,添加“选项组”和“选项值”。在老的项目里面这块实现的比较粗糙,我想研究下有没有什么好的改进方案,使得最终提交的所有 SKU 次序妥当,符合插入时的位置。
例如我设定选项组为“大小、颜色”,那么 SKU 就默认按照这个次序展示在下面,提供价格、库存等数据的编辑功能。(编辑结合了 React 的 Context
和 useReducer
不是很麻烦,修改哪行就写到哪行)
- 选项组:例如大小、颜色
- 选项值:例如小、大、红色、黄色
- SKU(变体):例如小、红色就是其中一个,上述组合一共会有
2 * 2 = 4
个
添加选项组,默认只会存在一个选项值,在插入第一个选项值的时候,默认所有 SKU 都会是第一个选项值。例如添加一个“款式”选项组,默认只有一个“经典”款,那么此时组合还是只有 2 * 2 * 1 = 4
个。
小、红色、经典 <-- 直接从「小、红色」变成「小、红色、经典」
小、黄色、经典
大、红色、经典
大、黄色、经典
假设我要增加一个颜色,那么此时组合就变成 2 * 3 * 1 = 6
个,需要增加两个 SKU,那么问题来了,如何确定新增的两条 SKU 要被放在哪个位置?这就是我想要解决的问题核心点了。
我尝试了很多方法,首先是直接拿 SKU 列表来遍历,只要插入了一个“选项值”,就去找它前面的那一个数据,但这样做,貌似只能解决插入最后一组数据的位置,如果有三个“选项值”,就会出现问题了。
// 最后一组选项值
小、红色
小、黄色
<-- 插入一个「小、蓝色」,可以读取黄色来生成
大、红色
大、黄色
<-- 插入一个「大、蓝色」,可以读取黄色来生成
如果按照这种方法插入数据,那么结果就会变成这样:
// 非最后一组选项值
小、红色
小、黄色
大、红色
<-- 插入一个「超大、红色」
大、黄色
<-- 插入一个「超大、黄色」
这很明显是错误的,正确结果应该是将两个「超大」放在数组的最后面,复制「红黄」两个 SKU 才是正确的。
关于这个问题,我不禁陷入了沉思,关于这两种插入“选项值”的情况,我实在是没找出什么特别的规律出来,难不成要单独检查他是不是最后那一组?写两种插入算法?也不知道用什么方法实现会更科学合理。这东西就涉及到算法和数据结构的知识了,挺有难度了。
关于这个问题,晚上我也去问了问“资深前端”@Innei,他在公司也整过电商业务。结果他说这个功能很复杂,他没写过,都是他们组长写的(大概率工资不低)既然问他未果,那我就去问问真正的“巨佬”@Eric 吧,写后端的算法都不会太差的。
我也把这上面的内容大致和他用图文解释了一通,他很快就 Get 到了要点,说这种算法叫做“全组合”,起初就是认为是我不知道如何从零到一根据“选项组和值”生成一个这样的 SKU 列表。
可实际环境下,我这个列表并不是瞬间产生的,基本上是一条一条增加上去的。他提到了“二分查找”这个概念,又是我不明白的东西。说是这个数量应该不需要用到,直接硬加进去然后排序就行。
还有一种情况,就是压根 SKU 的实际存储次序不按上述想象的效果生成,而是根据“选项组和值”遍历生成“视觉上的排好序”?可这样做我感觉也不太靠谱。
最后他还提到了“笛卡尔积”的办法(说是比较摆烂但是好看),说白了就是键值对模式,一个 SKU 固定一个 Key
,然后根据“选项组和值”生成 Key,最后遍历展示,这样编辑过程确实就甭管次序了,但提交的时候和二次编辑的时候,还需要额外进行转换处理,也是一个问题。
总的来说,我现在也不太清楚上述的几种方法哪个实现起来是性能较好、实际代码也优雅的,只能明天继续看看这个问题了...