private static IEnumerable <TResult> GroupJoin <TOuter, TInner, TKey, TResult>( IEnumerable <TOuter> outer, IEnumerable <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, IEnumerable <TInner>, TResult> resultSelector, IComparer <TKey> keyComparer) { using (var leftEnumerator = outer.GetEnumerator()) using (var rightEnumerator = inner.GetEnumerator()) { EnumeratorState <TOuter> leftState = leftEnumerator.Next(); EnumeratorState <TInner> rightState = rightEnumerator.Next(); while (leftState.HasCurrent && rightState.HasCurrent) { switch (keyComparer.Compare(outerKeySelector(leftState.Current), innerKeySelector(rightState.Current))) { case -1: yield return(resultSelector(leftState.Current, new TInner[] { })); leftState = leftEnumerator.Next(); break; case 0: TKey currentRightKey = innerKeySelector(rightState.Current); IReadOnlyList <TInner> elements = new[] { rightState.Current } .Concat(rightEnumerator .TakeWhile(current => keyComparer.Compare(currentRightKey, innerKeySelector(current)) == 0, last => rightState = last)) .ToArray(); yield return(resultSelector(leftState.Current, elements)); TKey currentLeftKey = outerKeySelector(leftState.Current); foreach (var leftItem in leftEnumerator.TakeWhile(current => keyComparer.Compare(currentLeftKey, outerKeySelector(current)) == 0, last => leftState = last)) { yield return(resultSelector(leftItem, elements)); } break; case 1: rightState = rightEnumerator.Next(); break; } } while (leftState.HasCurrent) { yield return(resultSelector(leftState.Current, new TInner[] { })); leftState = leftEnumerator.Next(); } } }
private static IEnumerable <TResult> Join <TOuter, TInner, TKey, TResult>( IEnumerable <TOuter> outer, IEnumerable <TInner> inner, Func <TOuter, TKey> outerKeySelector, Func <TInner, TKey> innerKeySelector, Func <TOuter, TInner, TResult> resultSelector, IComparer <TKey> keyComparer) { using (var leftEnumerator = outer.GetEnumerator()) using (var rightEnumerator = inner.GetEnumerator()) { EnumeratorState <TOuter> leftState = leftEnumerator.Next(); EnumeratorState <TInner> rightState = rightEnumerator.Next(); while (leftState.HasCurrent && rightState.HasCurrent) { switch (keyComparer.Compare(outerKeySelector(leftState.Current), innerKeySelector(rightState.Current))) { case -1: leftState = leftEnumerator.Next(); break; case 0: yield return(resultSelector(leftState.Current, rightState.Current)); TKey currentRightKey = innerKeySelector(rightState.Current); List <TInner> elements = new List <TInner> { rightState.Current }; foreach (TInner rightItem in rightEnumerator.TakeWhile(current => keyComparer.Compare(currentRightKey, innerKeySelector(current)) == 0, last => rightState = last)) { elements.Add(rightItem); yield return(resultSelector(leftState.Current, rightItem)); } TKey currentLeftKey = outerKeySelector(leftState.Current); foreach (var leftItem in leftEnumerator.TakeWhile(current => keyComparer.Compare(currentLeftKey, outerKeySelector(current)) == 0, last => leftState = last)) { foreach (TInner rightItem in elements) { yield return(resultSelector(leftItem, rightItem)); } } break; case 1: rightState = rightEnumerator.Next(); break; } } } }
private static IEnumerable <T> Distinct <T>( IEnumerable <T> source, IComparer <T> comparer) { using (var enumerator = source.GetEnumerator()) { EnumeratorState <T> state = enumerator.Next(); while (state.HasCurrent) { yield return(state.Current); state = enumerator.SkipWhile(current => comparer.Compare(state.Current, current) == 0); } } }
private static IEnumerable <T> Intersect <T>( IEnumerable <T> left, IEnumerable <T> right, IComparer <T> comparer) { using (var leftEnumerator = left.GetEnumerator()) using (var rightEnumerator = right.GetEnumerator()) { EnumeratorState <T> leftState = leftEnumerator.Next(); EnumeratorState <T> rightState = rightEnumerator.Next(); while (leftState.HasCurrent && rightState.HasCurrent) { switch (comparer.Compare(leftState.Current, rightState.Current)) { case -1: leftState = leftEnumerator.Next(); break; case 0: yield return(leftState.Current); foreach (T item in leftEnumerator.TakeWhile( current => comparer.Compare(current, rightState.Current) == 0, last => leftState = last)) { yield return(item); } yield return(rightEnumerator.Current); foreach (T item in rightEnumerator.TakeWhile( current => comparer.Compare(current, rightState.Current) == 0, last => rightState = last)) { yield return(item); } break; case 1: rightState = rightEnumerator.Next(); break; } } } }
private static IEnumerable <T> Except <T>( IEnumerable <T> left, IEnumerable <T> right, IComparer <T> comparer) { using (var leftEnumerator = left.GetEnumerator()) using (var rightEnumerator = right.GetEnumerator()) { EnumeratorState <T> leftState = leftEnumerator.Next(); EnumeratorState <T> rightState = rightEnumerator.Next(); while (leftState.HasCurrent && rightState.HasCurrent) { switch (comparer.Compare(leftState.Current, rightState.Current)) { case -1: yield return(leftState.Current); leftState = leftEnumerator.Next(); break; case 0: leftState = leftEnumerator.SkipWhile(current => comparer.Compare(leftState.Current, current) == 0); rightState = rightEnumerator.SkipWhile(current => comparer.Compare(rightState.Current, current) == 0); break; case 1: rightState = rightEnumerator.Next(); break; } ; } while (leftState.HasCurrent) { yield return(leftState.Current); leftState = leftEnumerator.Next(); } } }
private static IEnumerable <IGrouping <TKey, T> > GroupBy <T, TKey>( IEnumerable <T> source, Func <T, TKey> keySelector, IComparer <TKey> keyComparer) { using (var enumerator = source.GetEnumerator()) { EnumeratorState <T> state = enumerator.Next(); while (state.HasCurrent) { TKey groupKey = keySelector(state.Current); IReadOnlyList <T> elements = new[] { state.Current } .Concat(enumerator .TakeWhile(current => keyComparer.Compare(groupKey, keySelector(current)) == 0, last => state = last)) .ToArray(); yield return(new Grouping <TKey, T>(groupKey, elements)); } } }