You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#生成多规格商品SKU组合结果异常问题排查

多规格商品SKU生成逻辑错误排查

需求背景

开发库存管理系统时需要实现多规格(变体)商品SKU自动生成功能,本质是计算所有变体选项的笛卡尔积。当前支持三类变体,可选值如下:

  • color:Black, Blue, Grey
  • size:S, M, L, XL
  • material:Cotton, Wool

现有代码在仅选择2种变体(比如color+size)时可以输出正确结果,新增第3种变体后输出不符合预期。
以商品名Jean为例,预期输出所有组合,格式如下:

  • Jean-Black/S/Cotton
  • Jean-Black/S/Wool
  • Jean-Black/M/Cotton
  • Jean-Black/M/Wool
  • Jean-Black/L/Cotton
  • Jean-Black/L/Wool
  • Jean-Black/XL/Cotton
  • Jean-Black/XL/Wool

  • Jean-Blue/S/Cotton
  • Jean-Blue/S/Wool
  • Jean-Blue/M/Cotton
  • Jean-Blue/M/Wool
  • Jean-Blue/L/Cotton
  • Jean-Blue/L/Wool
  • Jean-Blue/XL/Cotton
  • Jean-Blue/XL/Wool

  • Jean-Grey/S/Cotton
  • Jean-Grey/S/Wool
  • Jean-Grey/M/Cotton
  • Jean-Grey/M/Wool
  • Jean-Grey/L/Cotton
  • Jean-Grey/L/Wool
  • Jean-Grey/XL/Cotton
  • Jean-Grey/XL/Wool

现有代码

页面绑定模型

public class CreateModel : PageModel
{
    [Required]
    [BindProperty]
    public string? Name { get; set; }

    [BindProperty]
    public List<ProductVariantModel> Variants { get; set; }
    
}

创建商品页面

变体项模型

public class ProductVariantModel
{
    public string? Name { get; set; }

    public string? Options { get; set; }
}

SKU生成核心逻辑

List<ProductVariantOption> productOptions = new();
try
{
    int variantsTotal = model.Variants.Count;

    for (int a = 0; a < variantsTotal; a++)
    {
        string[] options = model.Variants[a].Options.Split(',');
        for (int i = 0; i < options.Length; i++)
        {
            string? option = $"{model.Name}-{options[i]}";
            if (variantsTotal > 1)
            {
                int index = a + 1;
                if (index < variantsTotal)
                {
                    var levelBelowOptions = model.Variants[index].Options.Split(',');
                    var ops = GetOptions(option, levelBelowOptions);
                    productOptions.AddRange(ops);
                }
            }
        }
        a += 1;
    }
}

选项拼接方法

private List<ProductVariantOption> GetOptions(string option, string[] options)
{
    List<ProductVariantOption> variantOptions = new();

    for (int i = 0; i < options.Length; i++)
    {
        string sku = $"{option}/{options[i]}";
        string opt = $"{option}/{options[i]}";
        variantOptions.Add(new ProductVariantOption(opt, sku));
    }

    return variantOptions;
}

SKU实体定义

public class ProductVariantOption
{
    public string Name { get; private set; }

    public string SKU { get; private set; }

    public Guid ProductVariantId { get; private set; }

    public ProductVariant ProductVariant { get; private set; }

    public ProductVariantOption(string name, string sku)
    {
        Guard.AgainstNullOrEmpty(name, nameof(name));

        Name = name;
        SKU = sku;
    }
}

逻辑错误说明

现有代码共3处核心问题,2种变体时属于巧合能正常运行,3种及以上变体就会完全失效:

  1. 外层循环索引重复自增:外层for循环本身已经定义了a++的自增逻辑,循环块末尾又额外写了a += 1,相当于每次循环a的索引直接加2。2种变体时,a初始值为0,进入循环处理第一个变体,走完循环块a变成1,触发for循环的a++后变成2,刚好满足退出条件,不会触发异常;3种变体时,第一次循环走完a变成1,for自增后变成2,直接跳过了索引为1的size变体,进入material层级的循环,完全漏掉size维度的选项。
  2. 拼接逻辑硬编码仅支持2层:现有逻辑拿到当前层的选项后,只会取下一个相邻层级的选项做拼接,GetOptions方法拼完相邻层就直接返回结果,没有继续处理后续剩余层级的逻辑,3种变体时最多只能拼出2段的SKU,根本不会带上第三层material的选项。
  3. 循环起始维度错误:外层循环会把每个变体层级都当作组合的起始点处理,而笛卡尔积计算只需要从第一个维度开始,逐层向后累积拼接即可,多起始点遍历会生成大量缺项、重复的无效SKU。

修复思路

放弃硬编码两层的拼接写法,改用通用笛卡尔积累积逻辑:先把第一个变体的所有选项作为初始结果集,然后依次遍历后续每一个变体,把当前结果集里的每一项和当前变体的所有选项做交叉拼接,替换原来的结果集,直到所有变体维度遍历完成,即可支持任意数量的变体组合。

内容的提问来源于stack exchange,提问作者Edgias

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 20:01:22