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
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/274761.html
標籤:其他
