IEnumerable扩展左连接 方法
using System; using System.Collections.Generic; using System.Linq; namespace Project.Lib { /// <summary> /// IEnumerable扩展左连接的三种方法 /// </summary> public static class IEnumerableExtensions { public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(this IEnumerable<TLeft> left, IEnumerable<TRight> right, Func<TLeft, TKey> leftKey, Func<TRight, TKey> rightKey, Func<TLeft, TRight, TResult> result) { return left.GroupJoin(right, leftKey, rightKey, (l, r) => new { l, r }) .SelectMany( o => o.r.DefaultIfEmpty(), (l, r) => new { lft = l.l, rght = r }) .Select(o => result.Invoke(o.lft, o.rght)); } public static IEnumerable<TResult> LeftJoin<TOuter, TInner, TKey, TResult>(this IEnumerable<TOuter> outer, IEnumerable<TInner> inner, Func<TOuter, TKey> outerKeySelector, Func<TInner, TKey> innerKeySelector, Func<TOuter, TInner, TResult> resultSelector) { return outer .GroupJoin(inner, outerKeySelector, innerKeySelector, (outerObj, inners) => new { outerObj, inners = inners.DefaultIfEmpty() }) .SelectMany(a => a.inners.Select(innerObj => resultSelector(a.outerObj, innerObj))); } public static IEnumerable<Result> LeftJoin<TOuter, TInner, TKey, Result>( this IEnumerable<TOuter> outer , IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector , Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector , IEqualityComparer<TKey> comparer) { if (outer == null) throw new ArgumentException("outer"); if (inner == null) throw new ArgumentException("inner"); if (outerKeySelector == null) throw new ArgumentException("outerKeySelector"); if (innerKeySelector == null) throw new ArgumentException("innerKeySelector"); if (resultSelector == null) throw new ArgumentException("resultSelector"); return LeftJoinImpl(outer, inner, outerKeySelector, innerKeySelector, resultSelector, comparer ?? EqualityComparer<TKey>.Default); } static IEnumerable<Result> LeftJoinImpl<TOuter, TInner, TKey, Result>( IEnumerable<TOuter> outer, IEnumerable<TInner> inner , Func<TOuter, TKey> outerKeySelector , Func<TInner, TKey> innerKeySelector , Func<TOuter, TInner, Result> resultSelector , IEqualityComparer<TKey> comparer) { var innerLookup = inner.ToLookup(innerKeySelector, comparer); foreach (var outerElment in outer) { var outerKey = outerKeySelector(outerElment); var innerElements = innerLookup[outerKey]; if (innerElements.Any()) foreach (var innerElement in innerElements) yield return resultSelector(outerElment, innerElement); else yield return resultSelector(outerElment, default(TInner)); } } } }