购物车多sku组合查询算法

基于项目中用到的多sku 选择的问题,提几点参考意见

  • 思路
  • 示例代码
  • github

思路

针对多sku 选择的问题,当选中某一个规格的时候,目的是需要匹配出所有包含当前此项的所有可能的sku,随后视图显示出来直到选择到具体的sku。比如规格中有 红色L码32,黄色m码30,蓝色L码32 三个规格。选中红色,在尺码一栏和大小一栏 只能有对应的“L码”和”32”显示,选择L码,颜色一栏中 “红色”和“蓝色”都可以点亮。如何实现这个目标呢,

  1. 分拆。将每一个具体的SKU 拆分出具体的组合,例如红色L码32,可以拆出的组合是红色,L码,32,红色L码,红色32,L码32,红色L码32。 得到一组所有的子规格合并组合
  2. 选择的时候,合并过滤。例 选择L码,红色,在大小栏中只有 32 可点击,但是在颜色一栏中,蓝色是处于可点击状态。当选中某一项的时候,需要在当前子规格栏 用其他选中的子规格依次拼接每一个查询是否存在相应的规格(这块需要额外理解一下)。比如需要用选中的L码和32 依次 拼接“红色”,”蓝色”去查询是否存在此sku。
注意事项
  • 初始化的时候需要扫描一遍所有sku的库存,无库存不可用
  • 通过sku 的 option项进行拼接的时候需要考虑,多option情况下值一致的问题(数据或sku设定可能导致一致),例如 大小 : 32, XL,尺码 : XL,M (这种情况下会导致选中状态下的bug)
  • 数据排序

讲解比较抽象,可以参考code进行思考


源码参考

code以作者自身项目中的表结构为例讲解,具体请参考ChooseSkuDemo
分拆数据的过程中的源码处理,例如:

// 组合算法 从m中获取n个元素
- (NSArray *)valueFromTotal:(NSInteger)m
                      count:(NSInteger)n
{
    // 首先初始化,将数组前n个元素置1,表示第一个组合为前n个数。
    NSMutableArray *nArry = [[NSMutableArray alloc]init];
    for (NSInteger i = 0; i<m; i++) {
        [nArry addObject:@(i<n?1:0)];
    }

    if (m == n) {
        return @[nArry];
    }

    NSMutableArray *resault = [[NSMutableArray alloc]init];
    // 全排第一次
    [resault addObject:[nArry copy]];

    BOOL isend = false;
    //然后从左到右扫描数组元素值的“10”组合,找到第一个“10”组合后将其变为“01”组合
    while (!isend) {
        // 从后往前走--一遍循环结束
        NSInteger leftTotal1 = 0;      //左侧的1的数量
        for (NSInteger i = 0; i < m-1; i++) {
            if ([nArry[i] intValue] == 1 && [nArry[i+1] intValue] == 0) {
                // 然后左侧的所有的1 移到最左侧
                for (NSInteger j = 0; j<i; j++) {
                    nArry[j] = @(j<leftTotal1?1:0);
                }

                // 找到第一个 10组合 变成 01
                [nArry exchangeObjectAtIndex:i withObjectAtIndex:i+1];
                [resault addObject:[nArry copy]];

                // 当第一个“1”移动到数组的m-n的位置,即n个“1”全部移动到最右端时,就得到了最后一个组合。
                if ([nArry indexOfObject:@1] == m-n) {
                    isend = true;
                }

                break;  //一次循环结束--可以重新执行了
            }

            // 左侧多少个1
            if ([nArry[i] intValue] == 1) {
                leftTotal1++;
            }
        }
    }

    return resault;
}

得到所有可能的option组合

    - (NSArray *)arryCombineFromSource:(NSArray *)source
{
    if (source.count == 0) return nil;

    NSMutableArray *resault = [[NSMutableArray alloc]init];
    for (NSInteger i = 1; i <= source.count; i++) {
        // Cn1  从n中取m个元素 顺序列出来
        NSArray *arry = [self valueFromTotal:source.count count:i];

        // 按照1的位置取出相应的元素[[1,0],[1],[0,1]]
        for (NSInteger j = 0; j<arry.count; j++) {
            NSMutableArray *value = [[NSMutableArray alloc]init];
            NSArray *arryj = arry[j];
            for (NSInteger k = 0;k<[arryj count]; k++) {
                if ([arry[j][k] intValue] == 1) {
                    [value addObject:source[k]];
                }
            }
            [resault addObject:[value mutableCopy]];
        }
    }
    return resault;
}

开始的时候所有sku的扫描部分

// 初始化得到结果集
- (void)initSkus
{
    @autoreleasepool {
        // 根据现有的sku 字段 去重新排列可能有的所有情况
        NSDictionary *optionDict = [self getAllSkuOptionKeys];
        NSArray *keys = [optionDict allKeys];
        for (NSInteger i = 0; i<keys.count; i++) {
            NSString *skuKey = keys[i];
            // 内容
            AMDSupplySkuModel *model = _allSkuOptionValues[skuKey];
            AYEOptionQuantityModel *optionModel = [[AYEOptionQuantityModel alloc]init];
            optionModel.optionValue = [model allOptionValue];
            optionModel.quantity = model.quantity;
            optionModel.quantity_setting = model.quantity_setting;

            NSArray *skuKeysAttrs = [skuKey componentsSeparatedByString:@";"];

            // 将商品规格属性排列(按ASII码排列)
            skuKeysAttrs = [skuKeysAttrs sortedArrayUsingSelector:@selector(compare:)];

            // 对每个SKU信息key属性值进行拆分组合
            // 并把结果集放入到集合
            NSArray *flagArry = [self arryCombineFromSource:skuKeysAttrs];
            for (NSInteger i =0; i < flagArry.count; i++) {
                NSArray *flag = flagArry[i];
                [self addSkuResaultWithKey:flag model:optionModel];
            }
        }

        // 处理相应的键值
        self.allSkuCombineKeys = [_allSkuCombinateResault allKeys];
    }
}

Github

源码地址: https://github.com/xie244135119/ChooseSkuDemo

希望可以帮助有需要的人,如果有疑问,也可以互相交流

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值