LINQ - Full Outer Join

后端 未结 16 1567
既然无缘
既然无缘 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:11

    I've written this extensions class for an app perhaps 6 years ago, and have been using it ever since in many solutions without issues. Hope it helps.

    edit: I noticed some might not know how to use an extension class.

    To use this extension class, just reference its namespace in your class by adding the following line using joinext;

    ^ this should allow you to to see the intellisense of extension functions on any IEnumerable object collection you happen to use.

    Hope this helps. Let me know if it's still not clear, and I'll hopefully write a sample example on how to use it.

    Now here is the class:

    namespace joinext
    {    
    public static class JoinExtensions
        {
            public static IEnumerable FullOuterJoin(
                this IEnumerable outer,
                IEnumerable inner,
                Func outerKeySelector,
                Func innerKeySelector,
                Func resultSelector)
                where TInner : class
                where TOuter : class
            {
                var innerLookup = inner.ToLookup(innerKeySelector);
                var outerLookup = outer.ToLookup(outerKeySelector);
    
                var innerJoinItems = inner
                    .Where(innerItem => !outerLookup.Contains(innerKeySelector(innerItem)))
                    .Select(innerItem => resultSelector(null, innerItem));
    
                return outer
                    .SelectMany(outerItem =>
                    {
                        var innerItems = innerLookup[outerKeySelector(outerItem)];
    
                        return innerItems.Any() ? innerItems : new TInner[] { null };
                    }, resultSelector)
                    .Concat(innerJoinItems);
            }
    
    
            public static IEnumerable LeftJoin(
                this IEnumerable outer,
                IEnumerable inner,
                Func outerKeySelector,
                Func innerKeySelector,
                Func resultSelector)
            {
                return outer.GroupJoin(
                    inner,
                    outerKeySelector,
                    innerKeySelector,
                    (o, i) =>
                        new { o = o, i = i.DefaultIfEmpty() })
                        .SelectMany(m => m.i.Select(inn =>
                            resultSelector(m.o, inn)
                            ));
    
            }
    
    
    
            public static IEnumerable RightJoin(
                this IEnumerable outer,
                IEnumerable inner,
                Func outerKeySelector,
                Func innerKeySelector,
                Func resultSelector)
            {
                return inner.GroupJoin(
                    outer,
                    innerKeySelector,
                    outerKeySelector,
                    (i, o) =>
                        new { i = i, o = o.DefaultIfEmpty() })
                        .SelectMany(m => m.o.Select(outt =>
                            resultSelector(outt, m.i)
                            ));
    
            }
    
        }
    }
    

提交回复
热议问题