Seems to work ...:
void Main()
{
var a = new int?[] {150, 100, 70, 30, 20 };
var b = new int?[] {300, 200, 100, 70, 60, 50, 20 };
var result = IndexDelta(a, b);
result.Dump();
}
// Define other methods and classes here
IObservable<Tuple<int, bool>> IndexDelta(IEnumerable<int?> a, IEnumerable<int?> b)
{
var observable = Observable.Create<Tuple<int, bool>>(o => {
var indexA = 0;
var indexB = 0;
var aEnumerator = a.GetEnumerator();
var bEnumerator = b.GetEnumerator();
var aHasNext = aEnumerator.MoveNext();
var bHasNext = bEnumerator.MoveNext();
while(true) {
if (aHasNext == false && bHasNext == false) {
"Completed".Dump();
o.OnCompleted(); // both sequences are over
break;
}
var headA = aEnumerator.Current;
var headB = bEnumerator.Current;
headA.Dump("A");
headB.Dump("B");
Action reportDeletion = () => {
o.OnNext(Tuple.Create(indexA, false));
aHasNext = aEnumerator.MoveNext(); // this one is fast
};
Action reportInsertion = () => {
o.OnNext(Tuple.Create(indexB, true));
bHasNext = bEnumerator.MoveNext(); // can take a long time
};
if (headA == null) { // No source item at this position
reportInsertion();
continue;
}
if (headB == null) { // No fetched item at this position
reportDeletion();
continue;
}
switch (headB.Value.CompareTo(headA.Value)) {
case 0:
aHasNext = aEnumerator.MoveNext();
bHasNext = bEnumerator.MoveNext();
indexA++;
indexB++;
break;
case 1: // Fetched item is newer than source item
reportInsertion();
indexB++;
break;
case -1: // Source item is newer than fetched item
reportDeletion();
indexA++;
break;
}
}
return Disposable.Empty;
});
return observable;
}