这是我最终得到的代码。我非常喜欢它,尤其是选择器,它意味着调用者可以决定在每个场景中返回什么:
public static class OrderedReconcileExtension
{
public static IEnumerable<TResult>
ReconcileWith<T, U, TResult>(this IEnumerable<T> left,
IEnumerable<U> right,
Func<T, U, int> comparison,
Func<T, U, TResult> selector)
{
return ReconcileHelper(new EnumerableIterator<T>(left),
new EnumerableIterator<U>(right),
comparison, selector);
}
private static IEnumerable<TResult>
ReconcileHelper<T, U, TResult>(EnumerableIterator<T> left,
EnumerableIterator<U> right,
Func<T, U, int> comparison,
Func<T, U, TResult> selector)
{
while (left.IsValid && right.IsValid)
{
// While left < right, the items in left aren't in right
while (left.IsValid && right.IsValid &&
comparison(left.Current, right.Current) < 0)
{
yield return selector(left.Current, default(U));
left.MoveNext();
}
// While right < left, the items in right aren't in left
while (left.IsValid && right.IsValid &&
comparison(left.Current, right.Current) > 0)
{
yield return selector(default(T), right.Current);
right.MoveNext();
}
// While left == right, the items are in both
while (left.IsValid && right.IsValid &&
comparison(left.Current, right.Current) == 0)
{
yield return selector(left.Current, right.Current);
left.MoveNext();
right.MoveNext();
}
}
// Mop up.
while (left.IsValid)
{
yield return selector(left.Current, default(U));
left.MoveNext();
}
while (right.IsValid)
{
yield return selector(default(T), right.Current);
right.MoveNext();
}
}
}
EnumerableIterator 与我在另一个问题中发布的代码完全相同。
更新:“一模一样”除了 IsValid 更改为 HasCurrent。选择一个。