-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathLinqExtensions.cs
83 lines (47 loc) · 1.64 KB
/
LinqExtensions.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace ATIMO
{
public static class LinqExtensions
{
public static IEnumerable<TResult> FullOuterJoin<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
IEnumerable<TInner> inner,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector)
{
if (outer == null)
{
throw new ArgumentNullException("outer");
}
if (inner == null)
{
throw new ArgumentNullException("inner");
}
if (outerKeySelector == null)
{
throw new ArgumentNullException("outerKeySelector");
}
if (innerKeySelector == null)
{
throw new ArgumentNullException("innerKeySelector");
}
if (resultSelector == null)
{
throw new ArgumentNullException("resultSelector");
}
var innerLookup = inner.ToLookup(innerKeySelector);
var outerLookup = outer.ToLookup(outerKeySelector);
var allKeys = (from i in innerLookup select i.Key).Union(
from o in outerLookup select o.Key);
var result = from key in allKeys
from innerElement in innerLookup[key].DefaultIfEmpty()
from outerElement in outerLookup[key].DefaultIfEmpty()
select resultSelector(outerElement, innerElement);
return result;
}
}
}