Search code examples
c#linqtuplesmorelinq

MoreLinq ExceptBy with only one matching property


I have 2 different items that I'm trying to perform the except by method using the more linq library. The only thing that is common between both items is a single string called Symbol. Item 1 is a list of tuples and Item 2 is a database table that I open with linq

Item 1:

Tuple<string Symbol, string Market, List<Class1>, List<Class2>>

Item 2:

List<TableClass>

TableClass {
string Symbol;
decimal Price;
bool isSold; }

Here is the code I attempted. I'm trying to return all elements from Item1 that don't exist in Item2:

Item1.ExceptBy(Item2.Select(k => k.Symbol), e => e.Symbol);

This doesn't work because Item1 and Item2 are completely different types

The type arguments for method 'MoreEnumerable.ExceptBy(IEnumerable, IEnumerable, Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly.


Solution

  • I keep an extension method handy for doing left outer joins:

    public static IEnumerable<TResult> LeftOuterJoin<TLeft, TRight, TKey, TResult>(
        this IEnumerable<TLeft> leftSeq,
        IEnumerable<TRight> rightSeq,
        Func<TLeft, TKey> keySelectorLeft,
        Func<TRight, TKey> keySelectorRight,
        Func<TLeft, TRight, TResult> projectionSelector)
    {
        return leftSeq
            .GroupJoin(
                rightSeq,
                keySelectorLeft,
                keySelectorRight,
                (leftItem, rightItems) => new { leftItem, rightItems })
            .SelectMany(
                x => x.rightItems.DefaultIfEmpty(),
                (x, rightItem) => projectionSelector(x.leftItem, rightItem));
    }
    

    So now we can:

    tuples.LeftOuterJoin(list, t => t.Symbol, k => k.Symbol, (t,k) => (t,k))
          .Where(x => x.k == null)
          .Select(x => x.t)
    

    ...and this will give us all the items from the tuple list with a Symbol property that does not have a corresponding item in the other list with the same Symbol. Right?