Writing this in an imperative way, you'd probably use some accumulator variables, then loop over the input values and manipulate the accumulators as necessary.
The closest parallel in functional programming is a scan (represented in ReactiveCocoa as -scanWithStart:reduce:
). A scan allows you to "thread" state through the stream and make use of it whenever a new input value arrives.
The result looks pretty similar to imperative accumulation, except that any mutation doesn't escape the scan block:
RACSignal *output = [[[[input
map:^(NSString *combo) {
NSArray *components = [combo componentsSeparatedByString:@","];
NSInteger number = [components[1] integerValue];
return RACTuplePack(components[0], @(number));
}]
// We need four state parameters:
// 1. The letter we're waiting for.
// 2. The number we're waiting for.
// 3. Values received that cannot be forwarded until a certain
// letter/number.
// 4. The values to forward at each step.
scanWithStart:RACTuplePack(@"A", @1, @[], @[]) reduce:^(RACTuple *state, RACTuple *letterAndNumber) {
NSString *waitingLetter = state[0];
NSNumber *waitingNumber = state[1];
NSArray *queuedValues = state[2];
// Enqueue this value until we're ready to send it (which may or may not
// occur on this step of the scan).
queuedValues = [queuedValues arrayByAddingObject:letterAndNumber];
if ([letterAndNumber.first isEqual:waitingLetter] && [letterAndNumber.second isEqual:waitingNumber]) {
// Determine the next letter and number.
waitingLetter = …;
waitingNumber = @(waitingNumber.integerValue + 1);
// Sort queuedValues lexically and numerically.
NSArray *forwardValues = …;
// We should no longer have any values queued, since we want to
// forward them all.
return RACTuplePack(waitingLetter, waitingNumber, @[], forwardValues);
} else {
// No values should escape the scan yet. Just pass on our queued
// values.
return RACTuplePack(waitingLetter, waitingNumber, queuedValues, @[]);
}
}]
map:^(RACTuple *state) {
// Convert the array of values into a signal.
NSArray *forwardValues = state.last;
return forwardValues.rac_sequence.signal;
}]
// Forward values from each inner signal in the correct, sorted order.
concat];
I've omitted some of the sorting logic for brevity, but that's pretty easy to fill in with the exact details of your algorithm.