57 lines
1.6 KiB
C#
57 lines
1.6 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
|
|
namespace InventoryTraker.Web.Utilities
|
|
{
|
|
public static class IEnumerableExtensions
|
|
{
|
|
public static IEnumerable<TResult> FullOuterGroupJoin<TA, TB, TKey, TResult>(
|
|
this IEnumerable<TA> a,
|
|
IEnumerable<TB> b,
|
|
Func<TA, TKey> selectKeyA,
|
|
Func<TB, TKey> selectKeyB,
|
|
Func<IEnumerable<TA>, IEnumerable<TB>, TKey, TResult> projection,
|
|
IEqualityComparer<TKey> cmp = null)
|
|
{
|
|
cmp = cmp ?? EqualityComparer<TKey>.Default;
|
|
var alookup = a.ToLookup(selectKeyA, cmp);
|
|
var blookup = b.ToLookup(selectKeyB, cmp);
|
|
|
|
var keys = new HashSet<TKey>(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<TResult> FullOuterJoin<TA, TB, TKey, TResult>(
|
|
this IEnumerable<TA> a,
|
|
IEnumerable<TB> b,
|
|
Func<TA, TKey> selectKeyA,
|
|
Func<TB, TKey> selectKeyB,
|
|
Func<TA, TB, TKey, TResult> projection,
|
|
TA defaultA = default(TA),
|
|
TB defaultB = default(TB),
|
|
IEqualityComparer<TKey> cmp = null)
|
|
{
|
|
cmp = cmp ?? EqualityComparer<TKey>.Default;
|
|
var alookup = a.ToLookup(selectKeyA, cmp);
|
|
var blookup = b.ToLookup(selectKeyB, cmp);
|
|
|
|
var keys = new HashSet<TKey>(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;
|
|
}
|
|
}
|
|
} |