3

我需要有一个类似于 Haskell 的 ReactiveCocoa 函数break

break                   :: (a -> Bool) -> [a] -> ([a],[a])
break _ xs@[]           =  (xs, xs)
break p xs@(x:xs')
           | p x        =  ([],xs)
           | otherwise  =  let (ys,zs) = break p xs' in (x:ys,zs)

基本上返回一个元组,其第一个组件是所有匹配且在第一个匹配之前出现的项目。第二个组件是匹配的项目和列表的尾部(无论它们是否匹配)。

ReactiveCocoa 的直接翻译是

- (RACTuple *)breakSequence:(RACSequence *)seq withBlock:(BOOL(^)(NSString *))matchBlock
{
    id head = [seq head];
    if (matchBlock(head)) {
        return [RACTuple tupleWithObjects:[RACSequence empty], seq, nil];
    } else {
        RACTuple *t = [self breakSequence:[seq tail] withBlock:matchBlock];
        return [RACTuple tupleWithObjects:[RACSequence sequenceWithHeadBlock:^id{
            return head;
        } tailBlock:^RACSequence *{
            return [t first];
        }], [t second], nil];
    }
}

显然它可以工作,但由于breakSequence:seq withBlock:.

在 ReactiveCocoa 中实现此功能的最佳方法是什么?

谢谢 :-)

4

1 回答 1

2

我的另一个版本看起来有点难看,但有效,发布在下面。将使用@Justin Spahr-Summers 的建议。

- (RACTuple *)betterBreakSequence:(RACSequence *)seq withBlock:(BOOL(^)(NSString *))matchBlock
{
    RACSequence *left = [seq takeUntilBlock:matchBlock];
    NSNumber *count = [left foldLeftWithStart:@0 reduce:^id(NSNumber *accumulator, id value) {
        return [NSNumber numberWithInteger:[accumulator integerValue]+1];
    }];
    RACSequence *right = [seq skip:[count integerValue]];
    return [RACTuple tupleWithObjects:left, right, nil];
}
于 2013-09-13T18:19:36.793 回答