iOS 商品sku选择算法,mask匹配计算可选项,计算库存
https://gitee.com/dingdedou/sku-selection
-1通配 其他为下标
tree [
{
“颜色” : [
“白色”,
“黑色”,
“灰色”
]
},
{
“容量” : [
“100ml”,
“200ml”
]
},
{
“材质” : [
“玻璃”,
“塑料”
]
}
]
------stockList-------- (
“(\n 1,\n 0,\n 1\n),7”,
“(\n 1,\n 1,\n 0\n),7”,
“(\n 2,\n 1,\n 1\n),6”
)
—(
“-1”,
“-1”,
“-1”
)的库存:20
— 根据当前选项 (
“-1”,
“-1”,
“-1”
)
(
0,
“-1”,
“-1”
)—白色 库存0 不能选择
(
1,
“-1”,
“-1”
)—黑色 库存14 能选择
(
2,
“-1”,
“-1”
)—灰色 库存6 能选择
(
“-1”,
0,
“-1”
)—100ml 库存7 能选择
(
“-1”,
1,
“-1”
)—200ml 库存13 能选择
(
“-1”,
“-1”,
0
)—玻璃 库存7 能选择
(
“-1”,
“-1”,
1
)—塑料 库存13 能选择
代码
@interface SkuItemIndex : NSObject
@property (assign, nonatomic) int index;//-1 未选择,0 to n-1 实际选择的
+ (instancetype)maskIndex;
+ (instancetype)indexOfInt:(int)index;
- (void)plusplus;
- (BOOL)isMask;
- (BOOL)isEqual2:(SkuItemIndex *)object;
- (int)intValue;
- (instancetype)copy;
- (NSString *)description;
@end
@interface SKUStockItem : NSObject
@property (assign, nonatomic) NSInteger stock;//库存
@property (strong, nonatomic) NSArray<SkuItemIndex *> *indexArr;//库存索引
@end
@interface SelectingCombination : NSObject
@property (strong, nonatomic) NSArray *stockList;//库存列表
@property (strong, nonatomic) NSArray *skuTree;//排序sku
@implementation SelectingCombination
//根据mask计算库存
- (NSInteger)stockOfIndexArr:(NSArray<SkuItemIndex *> *)indexArr{
NSInteger count = 0;
NSArray<NSArray<SkuItemIndex *> *> *subSet = [self subSetOfSkuIndex:indexArr];
for (NSArray<SkuItemIndex *> *indexArr in subSet) {
//每个item
for (SKUStockItem *stockItem in self.stockList) {
//找到item
if ([self indexOf:indexArr in:[self skuTreeNumArr]] == [self indexOf:stockItem.indexArr in:[self skuTreeNumArr]]) {
count = stockItem.stock + count;
break;
}
}
}
return count;
}
//MARK: -计算可选子集
- (NSArray<NSArray<SkuItemIndex *> *> *)subSetOfSkuIndex:(NSArray<SkuItemIndex *> *)skuIndex{
NSMutableArray *rTemp = [NSMutableArray array];
//找到没有选定的index选项的下标
NSMutableArray *maskIndexArr = [NSMutableArray array];
for (int i = 0; i < skuIndex.count; i++) {
SkuItemIndex *item = skuIndex[i];
if (item.isMask) {
SkuItemIndex *flag = [SkuItemIndex indexOfInt:i];
[maskIndexArr addObject:flag];
}
}
if (maskIndexArr.count == 0) {
//每个规格都选定了
return [NSArray arrayWithObject:[self copyIndexArr:skuIndex]];
}
//没有选定能形成的组合数
int totalCount = [self calMul:maskIndexArr];
//1计算下标组合
//1.1计算目标数组
NSArray *inArr = [self calDestArr:maskIndexArr];
//1.2根据线型index计算组合
for (int i = 0; i < totalCount; i++) {
NSArray<SkuItemIndex *> *indexArr = [self skuIndexArrFromLine:i inArray:inArr];
NSEnumerator<SkuItemIndex *> *iterator = indexArr.objectEnumerator;
//1.3组装新的index
NSMutableArray *skuIndexNew = [NSMutableArray arrayWithArray:[self copyIndexOf:skuIndex]];
//1.3.1找到没有选定的位置,并设置为新的值
for (SkuItemIndex *maskItemIndex in maskIndexArr) {
SkuItemIndex *maskItem = skuIndexNew[maskItemIndex.index];
maskItem.index = iterator.nextObject.index;
}
[rTemp addObject:skuIndexNew];
}
return rTemp;
}
//MARK: -复制数组
- (NSArray<SkuItemIndex *> *)copyIndexOf:(NSArray<SkuItemIndex *> *)indexArr{
NSMutableArray *rArr = [NSMutableArray array];
for (SkuItemIndex *item in indexArr) {
[rArr addObject:item.copy];
}
return rArr;
}
//@param indexArray 组合的下标,必须选定下标
//@param baseArray 基于的组合 如@[@3,@3,@4]
//return 下标对应的index
- (NSUInteger)indexOf:(NSArray<SkuItemIndex *> *)indexArray in:(NSArray *)baseArray{
NSMutableArray *stArr = [NSMutableArray array];
int tmp = 1;
//计算进制位
[stArr addObject:[NSNumber numberWithInt:1]];//补一个最地位的进制
for (NSInteger i = baseArray.count - 1; i >= 0; i--) {
NSNumber *num = [baseArray objectAtIndex:i];
tmp = num.intValue * tmp;
NSNumber *total = [NSNumber numberWithInt:tmp];
[stArr addObject:total];
}
//计算index
NSArray *stArrEmumer = [[stArr reverseObjectEnumerator] allObjects];
NSUInteger r = 0;
for(NSUInteger i = 0; i < indexArray.count; i++){
SkuItemIndex *num = [indexArray objectAtIndex:i];
NSNumber *st = [stArrEmumer objectAtIndex:(i+1)];
r = num.intValue * st.integerValue + r;
}
return r;
}
//MARK: --
//@param index 组合的index
//@param baseArray 基于的组合 如@[@3,@3,@4]
//return index对应的下标
-(NSArray<SkuItemIndex *> *)skuIndexArrFromLine:(NSUInteger)index inArray:(NSArray *)baseArray{
NSMutableArray *rArr = [NSMutableArray array];
NSUInteger st = index;
NSMutableArray *stArr = [NSMutableArray array];
NSUInteger tmp = 1;
//计算进制位
[stArr addObject:[NSNumber numberWithInt:1]];//补一个最低位的进制
for (NSInteger i = baseArray.count - 1; i >= 0; i--) {
NSNumber *num = [baseArray objectAtIndex:i];
tmp = num.intValue * tmp;
NSNumber *total = [NSNumber numberWithInteger:tmp];
[stArr addObject:total];
}
//计算下标
NSArray *stArrEmumer = [[stArr reverseObjectEnumerator] allObjects];
for (NSUInteger i = 0; i < baseArray.count; i++) {
NSNumber *totalNum = [stArrEmumer objectAtIndex:(i+1)];
NSUInteger total = totalNum.intValue;
NSUInteger lastIndex = st/total;
SkuItemIndex *num = [SkuItemIndex indexOfInt:(int)lastIndex];
[rArr addObject:num];
//余数放入下一位计算
st = st%total;
}
return rArr;
}
//计算组合数量
- (int)calMul:(NSArray<SkuItemIndex *> *)array{
int count = 1;
for (int i = 0; i < array.count; i++) {
//找到规格数量
SkuItemIndex *index = array[i];
NSDictionary *skuSub = self.skuTree[index.index];
NSArray *items = skuSub.allValues.firstObject;
count = count*(int)items.count;
}
return count;
}
//根据index生成目标组合的数量数组,返回结果如@[@3,@2]
- (NSArray *)calDestArr:(NSArray<SkuItemIndex *> *)array{
NSMutableArray *rArr = [NSMutableArray array];
for (int i = 0; i < array.count; i++) {
//找到规格数量
SkuItemIndex *index = array[i];
NSArray *skuSubItems = [self skuTreeValueArr][index.index];
NSNumber *num = [NSNumber numberWithInteger:skuSubItems.count];
[rArr addObject:num];
}
return rArr;
}
//自身的数量数组,如@[@3,@2,@2]
- (NSArray *)skuTreeNumArr{
NSMutableArray *rArr = [NSMutableArray array];
NSArray *valueArr = [self skuTreeValueArr];
for (int i = 0; i < valueArr.count; i++) {
//找到规格数量
NSArray *items = valueArr[i];
NSNumber *num = [NSNumber numberWithInteger:items.count];
[rArr addObject:num];
}
return rArr;
}
//根据skuTree获取所有值的数组 如@[@[@"白色",@"黑色",@"灰色"],@[@"100ml",@"200ml"],@[@"玻璃",@"塑料"]];
-(NSArray<NSArray *> *)skuTreeValueArr{
NSMutableArray *rArr = [NSMutableArray array];
for (int i = 0; i < self.skuTree.count; i++) {
NSDictionary *skuSub = self.skuTree[i];
NSArray *items = skuSub.allValues.firstObject;
[rArr addObject:items];
}
return rArr;
}
//根据skuTree获取所有key的数组 如@[@"颜色"@"容量"@"材质"];
-(NSArray *)skuTreeKeyArr{
NSMutableArray *rArr = [NSMutableArray array];
for (int i = 0; i < self.skuTree.count; i++) {
NSDictionary *skuSub = self.skuTree[i];
NSString *key = skuSub.allKeys.firstObject;
[rArr addObject:key];
}
return rArr;
}
//复制indexArr
- (NSArray<SkuItemIndex *> *)copyIndexArr:(NSArray<SkuItemIndex *> *)indexArr{
NSMutableArray *rArr = [NSMutableArray array];
for (SkuItemIndex *index in indexArr) {
[rArr addObject:index.copy];
}
return rArr;
}
//all Mask
- (NSArray<SkuItemIndex *> *)allMask{
NSMutableArray *rArr = [NSMutableArray array];
for (int i = 0; i < self.skuTree.count; i++) {
SkuItemIndex *index = [SkuItemIndex maskIndex];
[rArr addObject:index];
}
return rArr;
}
@end
1.有了你,我什么都不缺,心再野,也该知道拒绝。 2.请不要拼命假装云淡风轻的...
一、微信支付 1、业务平台介绍 1微信公众平台 微信公众平台是微信公众账号申请入...
本文转载自微信公众号「DBA闲思杂想录」,作者潇湘隐者。转载本文请联系DBA闲思...
前言 所谓秘密拍卖就是在拍卖期间别人无法知道你的出价因此拍卖的所有出价都是由...
使用vue写出简单的购物车,供大家参考,具体内容如下 代码: // An highlighted ...
if rs.bof then 表示:当前指针的位置是在第一行记录之前 if rs.eof then 表示:...
个人认为PHP和JAVA有以下几点的区别 1、PHP多用去中小型企业而 java更加安全和稳...
1.说分手时,我以为我足够坚强,却还是红了眼眶。 2.在这世上,最容易变的是人...
目前微信公众号和小程序应用越来越多,那么我们如何对二者进行抓包进而在测试中...
1.xml文件: xml version="1.0" encoding="UTF-8"Students student id="2" namet...