LINQ - Full Outer Join

后端 未结 16 1560
既然无缘
既然无缘 2020-11-21 22:45

I have a list of people\'s ID and their first name, and a list of people\'s ID and their surname. Some people don\'t have a first name and some don\'t have a surname; I\'d l

16条回答
  •  忘了有多久
    2020-11-21 23:15

    Performs a in-memory streaming enumeration over both inputs and invokes the selector for each row. If there is no correlation at the current iteration, one of the selector arguments will be null.

    Example:

       var result = left.FullOuterJoin(
             right, 
             x=>left.Key, 
             x=>right.Key, 
             (l,r) => new { LeftKey = l?.Key, RightKey=r?.Key });
    
    • Requires an IComparer for the correlation type, uses the Comparer.Default if not provided.

    • Requires that 'OrderBy' is applied to the input enumerables

      /// 
      /// Performs a full outer join on two .
      /// 
      /// 
      /// 
      /// 
      /// 
      /// 
      /// 
      /// 
      /// 
      /// Expression defining result type
      /// A comparer if there is no default for the type
      /// 
      [System.Diagnostics.DebuggerStepThrough]
      public static IEnumerable FullOuterJoin(
          this IEnumerable left,
          IEnumerable right,
          Func leftKeySelector,
          Func rightKeySelector,
          Func selector,
          IComparer keyComparer = null)
          where TLeft: class
          where TRight: class
          where TValue : IComparable
      {
      
          keyComparer = keyComparer ?? Comparer.Default;
      
          using (var enumLeft = left.OrderBy(leftKeySelector).GetEnumerator())
          using (var enumRight = right.OrderBy(rightKeySelector).GetEnumerator())
          {
      
              var hasLeft = enumLeft.MoveNext();
              var hasRight = enumRight.MoveNext();
              while (hasLeft || hasRight)
              {
      
                  var currentLeft = enumLeft.Current;
                  var valueLeft = hasLeft ? leftKeySelector(currentLeft) : default(TValue);
      
                  var currentRight = enumRight.Current;
                  var valueRight = hasRight ? rightKeySelector(currentRight) : default(TValue);
      
                  int compare =
                      !hasLeft ? 1
                      : !hasRight ? -1
                      : keyComparer.Compare(valueLeft, valueRight);
      
                  switch (compare)
                  {
                      case 0:
                          // The selector matches. An inner join is achieved
                          yield return selector(currentLeft, currentRight);
                          hasLeft = enumLeft.MoveNext();
                          hasRight = enumRight.MoveNext();
                          break;
                      case -1:
                          yield return selector(currentLeft, default(TRight));
                          hasLeft = enumLeft.MoveNext();
                          break;
                      case 1:
                          yield return selector(default(TLeft), currentRight);
                          hasRight = enumRight.MoveNext();
                          break;
                  }
              }
      
          }
      
      }
      

提交回复
热议问题