Intersect LINQ query

C#.NetLinq

C# Problem Overview


If I have an IEnumerable where ClassA exposes an ID property of type long. Is it possible to use a Linq query to get all instances of ClassA with ID belonging to a second IEnumerable?

In other words, can this be done?

IEnumerable<ClassA> = original.Intersect(idsToFind....)?

where original is an IEnumerable<ClassA> and idsToFind is IEnumerable<long>.

C# Solutions


Solution 1 - C#

Yes.

As other people have answered, you can use Where, but it will be extremely inefficient for large sets.

If performance is a concern, you can call Join:

var results = original.Join(idsToFind, o => o.Id, id => id, (o, id) => o);

If idsToFind can contain duplicates, you'll need to either call Distinct() on the IDs or on the results or replace Join with GroupJoin (The parameters to GroupJoin would be the same).

Solution 2 - C#

I will post an answer using Intersect.

This is useful if you want to intersect 2 IEnumerables of the same type.

First we will need an EqualityComparer:

    public class KeyEqualityComparer<T> : IEqualityComparer<T>
    {
        private readonly Func<T, object> keyExtractor;

        public KeyEqualityComparer(Func<T, object> keyExtractor)
        {
            this.keyExtractor = keyExtractor;
        }

        public bool Equals(T x, T y)
        {
            return this.keyExtractor(x).Equals(this.keyExtractor(y));
        }

        public int GetHashCode(T obj)
        {
            return this.keyExtractor(obj).GetHashCode();
        }
    }

Secondly we apply the KeyEqualityComparer to the Intersect function:

var list3= list1.Intersect(list2, new KeyEqualityComparer<ClassToCompare>(s => s.Id));

Solution 3 - C#

You can do it, but in the current form, you'd want to use the Where extension method.

var results = original.Where(x => yourEnumerable.Contains(x.ID));

Intersect on the other hand will find elements that are in both IEnumerable's. If you are looking for just a list of ID's, you can do the following which takes advantage of Intersect

var ids = original.Select(x => x.ID).Intersect(yourEnumerable);

Solution 4 - C#

A simple way would be:

IEnumerable<ClassA> result = original.Where(a => idsToFind.contains(a.ID));

Solution 5 - C#

Use the Where method to filter the results:

var result = original.Where(o => idsToFind.Contains(o.ID));

Solution 6 - C#

Naming things is important. Here is an extension method base on the Join operator:

private static IEnumerable<TSource> IntersectBy<TSource, TKey>(
    this IEnumerable<TSource> source,
    IEnumerable<TKey> keys,
    Func<TSource, TKey> keySelector)
        => source.Join(keys, keySelector, id => id, (o, id) => o);

You can use it like this var result = items.IntersectBy(ids, item => item.id).

Solution 7 - C#

I've been tripping up all morning on Intersect, and how it doesn't work anymore in core 3, due to it being client side not server side.

From a list of items pulled from a database, the user can then choose to display them in a way that requires children to attached to that original list to get more information.

What use to work was:

itemList = _context.Item
        .Intersect(itemList)
        .Include(i => i.Notes)
        .ToList();

What seems to now work is:

itemList = _context.Item
        .Where(item => itemList.Contains(item))
        .Include(i => i.Notes)
        .ToList();

This seems to be working as expected, without any significant performance difference, and is really no more complicated than the first.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionKlaus NjiView Question on Stackoverflow
Solution 1 - C#SLaksView Answer on Stackoverflow
Solution 2 - C#Dragos DurlutView Answer on Stackoverflow
Solution 3 - C#David PfefferView Answer on Stackoverflow
Solution 4 - C#bruno condeView Answer on Stackoverflow
Solution 5 - C#Ahmad MageedView Answer on Stackoverflow
Solution 6 - C#aloisdgView Answer on Stackoverflow
Solution 7 - C#KopfsView Answer on Stackoverflow