如何使用ReactiveCocoa简化嵌套for循环



假设我有两个事先不知道的NSDictionaries,比如:

NSDictionary *dictA = @{ @"key1" : @1,
                         @"key2" : @2  };
NSDictionary *dictB = @{ @"key1" : @"a string" };

我想找到dictB的键和dictA的键或值之间的第一个匹配。dictB的每个键将是一个NSNumber或一个字符串。如果它是一个数字,请尝试从dictA中查找匹配项。如果是字符串,请尝试从dictA中查找匹配项。

使用for循环,它看起来像这样:

id match;
for (id key in dictA ) {
    for (id _key in dictB {
        if ( [_key is kindOfClass:NSNumber.class] && _key == dictA[key] ) {
            match = _key
            goto outer;
        }
        else if ( [_key is kindOfClass:NSString.class] && [_key isEqualToString:key] ) {
            match = _key
            goto outer;
        }
    }
};
outer:;
NSString *message = match ? @"A match was found" : @"No match was found";
NSLog(message);

我如何使用RACSequenceRACStream方法用ReactiveCocoa重写它,使其看起来像:

// shortened pseudo code:
// id match = [dictA.rac_sequence compare with dictB.rac_sequence using block and return first match];

您基本上想创建字典的笛卡尔乘积并对其进行选择。据我所知,ReactiveCocoa中没有默认的运算符可以为您做到这一点。(在LINQ中有运算符。)在RAC中,最简单的解决方案是使用scanWithStart:combine:方法来实现此操作。一旦笛卡尔坐标准备就绪,filter:take:1操作将生成您选择的序列。

NSDictionary *adic = @{@"aa":@"vb", @"ab": @"va"};
NSDictionary *bdic = @{@"ba": @"va", @"bb":@"vb"};;
RACSequence *aseq = adic.rac_keySequence;
RACSequence *bseq = bdic.rac_keySequence;
RACSequence *cartesian = [[aseq scanWithStart:nil combine:^id(id running, id next_a) {
    return [bseq scanWithStart:nil combine:^id(id running, id next_b) {
        return RACTuplePack(next_a, next_b);
    }];
}] flatten];
RACSequence *filteredCartesian = [cartesian filter:^BOOL(RACTuple *value) {
    RACTupleUnpack(NSString *key_a, NSString *key_b) = value;
    // business logic with keys
    return false;
}];
RACSequence *firstMatch = [filteredCartesian take:1];

相关内容

  • 没有找到相关文章

最新更新