LEFT OUTER JOIN in LINQ

后端 未结 22 2508
臣服心动
臣服心动 2020-11-21 04:49

How to perform left outer join in C# LINQ to objects without using join-on-equals-into clauses? Is there any way to do that with where clause? Corr

22条回答
  •  醉酒成梦
    2020-11-21 05:38

    An implementation of left outer join by extension methods could look like

    public static IEnumerable LeftJoin(
      this IEnumerable outer, IEnumerable inner
      , Func outerKeySelector, Func innerKeySelector
      , Func resultSelector, IEqualityComparer 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.Default);
      }
    
      static IEnumerable LeftJoinImpl(
          IEnumerable outer, IEnumerable inner
          , Func outerKeySelector, Func innerKeySelector
          , Func resultSelector, IEqualityComparer 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));
         }
       }
    

    The resultselector then has to take care of the null elements. Fx.

       static void Main(string[] args)
       {
         var inner = new[] { Tuple.Create(1, "1"), Tuple.Create(2, "2"), Tuple.Create(3, "3") };
         var outer = new[] { Tuple.Create(1, "11"), Tuple.Create(2, "22") };
    
         var res = outer.LeftJoin(inner, item => item.Item1, item => item.Item1, (it1, it2) =>
         new { Key = it1.Item1, V1 = it1.Item2, V2 = it2 != null ? it2.Item2 : default(string) });
    
         foreach (var item in res)
           Console.WriteLine(string.Format("{0}, {1}, {2}", item.Key, item.V1, item.V2));
       }
    

提交回复
热议问题