MoreLINQ icon indicating copy to clipboard operation
MoreLINQ copied to clipboard

UnionAll, IntersectAll, ExceptAll

Open JamesFaix opened this issue 9 years ago • 3 comments

LINQ's built-in "Union", "Except" and "Intersect" are somewhat odd among LINQ operators, as most others deal simply with enumerable collections, while these three treat enumerables as proper mathematical sets. Although this nicely mirrors SQL's Union, Intersect, and Except, LINQ does not provide an alternative like SQL's "All" keyword that will allow duplicate elements to be returned.

A working implementation can be found here: http://www.siepman.nl/blog/post/2013/08/19/Except-intersect-and-union-without-distinct.aspx

They could possibly also be implemented as overloads of the existing set operators, but with an optional boolean argument that can toggle "normal" distinct results vs "all" duplicate results.

Example method signature: public static IEnumerable<T> Union<T>(this IEnumerable<T> first, IEnumerable<T> second, bool all = false);
This would return the results of first.Union(second) if (all == false) and all duplicates in the result if (all == true).

These operators could also be combined with MoreLINQ's ExceptBy (and prospecitve IntersectBy, see #63 ).

I have found using an ExceptByAll type method essential for checking a DataColumn for duplicate values, and reporting back the row numbers of those duplicates.

JamesFaix avatar Nov 04 '15 23:11 JamesFaix

There is Concat, which is the same as SQL UNION ALL.

ExceptAll would be "left join where right hand is null", and IntersectAll woul be the same as "inner join, discard right hand side". But neither of these options expresses the intent clearly.

fsateler avatar Nov 05 '15 14:11 fsateler

I agree that a standard UnionAll is redundant with Concat. As for ExceptAll and IntersectAll being expressible with the help of Join, this is true, but as you mentioned, it does not express the intent clearly and LINQ Joins are very wordy to start with.

Several LINQ functions can also be reduced to others, like Last() to Skip(Math.Min(0, Count()-2)).Take(1), or Any(predicate) to Where(predicate).Count() > 1. Clarity of intent is a great way to eliminate errors before they happen.

Additionally I think there is room for ExcepAllBy, IntersectAllBy, and UnionAllBy variations, and the expressions that these could be reduced to (if in fact they can without semantic differences) would be a lot more complicated.

JamesFaix avatar Nov 06 '15 00:11 JamesFaix

Hi,

Has the newest library has this function yet ? I have read through all but see nowhere.

Thank you.

thelemontree10 avatar Apr 03 '20 13:04 thelemontree10