3

NSDictionaries次のように、事前にわからないものが2つあるとします。

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);

メソッドを使用RACSequenceして ReactiveCocoa でこれを書き直して、次のようにするにはどうすればよいでしょうか。RACStream

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

1 に答える 1

4

基本的に、辞書のデカルト積を作成し、それを選択します。私が知っているReactiveCocoaには、これを行うデフォルトの演算子はありません。(LINQ には、このための演算子があります。) RAC での最も簡単な解決策は、scanWithStart:combine:メソッドを使用してこの操作を実装することです。デカルトの準備が整うと、filter:andtake: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];
于 2013-09-01T20:35:56.043 に答える