fork(16) download
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4.  
  5. static class Program
  6. {
  7. static void Main(string[] args)
  8. {
  9. var ax = new[] {
  10. new { id = 1, name = "John" },
  11. new { id = 2, name = "Sue" } };
  12. var bx = new[] {
  13. new { id = 1, surname = "Doe" },
  14. new { id = 3, surname = "Smith" } };
  15.  
  16. ax.FullOuterJoin(bx, a => a.id, b => b.id, (a, b, id) => new {a, b})
  17. .ToList().ForEach(Console.WriteLine);
  18. }
  19. }
  20.  
  21. internal static class MyExtensions
  22. {
  23. internal static IList<TR> FullOuterGroupJoin<TA, TB, TK, TR>(
  24. this IEnumerable<TA> a,
  25. IEnumerable<TB> b,
  26. Func<TA, TK> selectKeyA,
  27. Func<TB, TK> selectKeyB,
  28. Func<IEnumerable<TA>, IEnumerable<TB>, TK, TR> projection,
  29. IEqualityComparer<TK> cmp = null)
  30. {
  31. cmp = cmp?? EqualityComparer<TK>.Default;
  32. var alookup = a.ToLookup(selectKeyA, cmp);
  33. var blookup = b.ToLookup(selectKeyB, cmp);
  34.  
  35. var keys = new HashSet<TK>(alookup.Select(p => p.Key), cmp);
  36. keys.UnionWith(blookup.Select(p => p.Key));
  37.  
  38. var join = from key in keys
  39. let xa = alookup[key]
  40. let xb = blookup[key]
  41. select projection(xa, xb, key);
  42.  
  43. return join.ToList();
  44. }
  45.  
  46. internal static IList<TR> FullOuterJoin<TA, TB, TK, TR>(
  47. this IEnumerable<TA> a,
  48. IEnumerable<TB> b,
  49. Func<TA, TK> selectKeyA,
  50. Func<TB, TK> selectKeyB,
  51. Func<TA, TB, TK, TR> projection,
  52. TA defaultA = default(TA),
  53. TB defaultB = default(TB),
  54. IEqualityComparer<TK> cmp = null)
  55. {
  56. cmp = cmp?? EqualityComparer<TK>.Default;
  57. var alookup = a.ToLookup(selectKeyA, cmp);
  58. var blookup = b.ToLookup(selectKeyB, cmp);
  59.  
  60. var keys = new HashSet<TK>(alookup.Select(p => p.Key), cmp);
  61. keys.UnionWith(blookup.Select(p => p.Key));
  62.  
  63. var join = from key in keys
  64. from xa in alookup[key].DefaultIfEmpty(defaultA)
  65. from xb in blookup[key].DefaultIfEmpty(defaultB)
  66. select projection(xa, xb, key);
  67.  
  68. return join.ToList();
  69. }
  70. }
  71.  
Success #stdin #stdout 0.07s 34376KB
stdin
Standard input is empty
stdout
{ a = { id = 1, name = John }, b = { id = 1, surname = Doe } }
{ a = { id = 2, name = Sue }, b =  }
{ a = , b = { id = 3, surname = Smith } }