这是我参与更文挑战的第8天,活动详情查看: 更文挑战
一个功能或者 UI 设计往往有多种解决方案,为了决定采用哪种解决方案,往往需要数据说话。所有只能做出两个版本来测试用户的不同反应,这就是 A/B 测试,也叫桶测试或分流测试,就好像统计学领域里面的双样本假设测试。
SkyLab 是一个 A/B 测试库,是由著名 AFNetworking 网络库和 Alamofire 网络库的作者 Mattt 所编写。SkyLab 由 Objective-C 编写,核心代码只有 200 行左右,现在已经被作者 archived。
SkyLab 采用 Block 的方式对外提供调用接口,来接收版本 A 和 B 的区别处理。这样设计的接口易用性非常高。
+ (void)abTestWithName:(NSString *)name
                     A:(void (^)())A
                     B:(void (^)())B;
复制代码SkyLab 一共提供了三种解决方案:
- 在两种方案中随机选出一种
- 在不同权重的方案中,根据权重随机选出一种
- 在多个条件中,随机选出几个条件。
被选中的方案保存在了 NSUserDefault 中,使得每个用户在使用过程中,不管是被随机到哪种解决方案,都能够保持相同的策略。
其中,最难的是如何根据不同的权重随机出对应的方案?比如,一共有 A、B、C、D 四种方案,被随机到的概率需要设置为 10%,20%,30%,40%,该如何设计算法呢?
这个问题本人在面试的时候被问道过。
下面是 SkyLab 的解决方案的步骤:
- 将所有方案的权重按照顺序不断的累加,将累加结果放到数组 mutableWeightedSums 中;
- 随机出一个 0 到权重总和的数字 r;
- 在 mutableWeightedSums 中找到第一个大于 r 的坐标 idx,这个 idx 就是被随机到的坐标。
下面是核心代码:
static id SLRandomKeyFromDictionaryWithWeightedValues(NSDictionary *dictionary) {
    if ([dictionary count] == 0) {
        return nil;
    }
    
    NSArray *keys = [dictionary allKeys];
    NSMutableArray *mutableWeightedSums = [NSMutableArray arrayWithCapacity:[keys count]];
    
    double total = 0.0;
    for (id key in keys) {
        total += [dictionary[key] doubleValue];
        [mutableWeightedSums addObject:@(total)];
    }
    
    dispatch_once(&srand48OnceToken, ^{
        srand48(time(0));
    });
    
    double r = drand48() * total;
    
    __block id randomObject = nil;
    [mutableWeightedSums enumerateObjectsUsingBlock:^(NSNumber *cumulativeWeightedSum, NSUInteger idx, BOOL *stop) {
        if (r <= [cumulativeWeightedSum doubleValue]) {
            randomObject = keys[idx];
            *stop = YES;
        }
    }];
    
    return randomObject;
}
复制代码SkyLab 也可以当做练手项目,写出一个 Swift 版本,可以查看本人写的版本。
© 版权声明
文章版权归作者所有,未经允许请勿转载。
THE END
    























![[桜井宁宁]COS和泉纱雾超可爱写真福利集-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/4d3cf227a85d7e79f5d6b4efb6bde3e8.jpg)

![[桜井宁宁] 爆乳奶牛少女cos写真-一一网](https://www.proyy.com/skycj/data/images/2020-12-13/d40483e126fcf567894e89c65eaca655.jpg)
