using System; using System.Collections.Generic; using System.Linq; namespace InventoryTraker.Web.Utilities { public static class IEnumerableExtensions { public static IEnumerable FullOuterGroupJoin( this IEnumerable a, IEnumerable b, Func selectKeyA, Func selectKeyB, Func, IEnumerable, TKey, TResult> projection, IEqualityComparer cmp = null) { cmp = cmp ?? EqualityComparer.Default; var alookup = a.ToLookup(selectKeyA, cmp); var blookup = b.ToLookup(selectKeyB, cmp); var keys = new HashSet(alookup.Select(p => p.Key), cmp); keys.UnionWith(blookup.Select(p => p.Key)); var join = from key in keys let xa = alookup[key] let xb = blookup[key] select projection(xa, xb, key); return join; } public static IEnumerable FullOuterJoin( this IEnumerable a, IEnumerable b, Func selectKeyA, Func selectKeyB, Func projection, TA defaultA = default(TA), TB defaultB = default(TB), IEqualityComparer cmp = null) { cmp = cmp ?? EqualityComparer.Default; var alookup = a.ToLookup(selectKeyA, cmp); var blookup = b.ToLookup(selectKeyB, cmp); var keys = new HashSet(alookup.Select(p => p.Key), cmp); keys.UnionWith(blookup.Select(p => p.Key)); var join = from key in keys from xa in alookup[key].DefaultIfEmpty(defaultA) from xb in blookup[key].DefaultIfEmpty(defaultB) select projection(xa, xb, key); return join; } } }