Fastest way to check whether a single element in common exists between two enumerables

.net, c#, linq

Solution

The LINQ intersect is going to reconstruct a new `HashSet` based on the input value no matter what you do, even if the input is already a `HashSet`. Its implementation mutates the hash set internally (which is how it avoids yielding duplicate values) so it is important to make a copy of the input sequence, even if it's already a `HashSet`.

You can create your own `Intersect` method that accepts a hashset, instead of populating a new one. To avoid mutating it though, you'll have to settle for a bag-based `Intersect`, rather than a set based `Intersect` (i.e., duplicates in the sequence will all be yielded). Clearly that's not a problem in your case:

public static IEnumerable<T> IntersectAll<T>(
    this HashSet<T> set, IEnumerable<T> sequence)
{
    foreach (var item in sequence)
        if (set.Contains(item))
            yield return item;
}

Now you can write:

SelectedProductIDs.InsersectAll(orderProductIDs).Any();

And the hashset won't need to be re-constructed each time.

Problem

I have a method I'm writing where I want to be able to filter orders based on whether they have one or more ordered products in them that exist in the selection of products made by the user. Currently I'm doing this with: ``` SelectedProductIDs.Intersect(orderProductIDs).Any() ``` executed on each order (~20,000 orders total in the database and expected to grow quickly), where both SelectedProducts and orderProductIDs are string[]. I've also attempted to use pre-generated HashSets for both SelectedProductIDs and orderProductIDs, but this made no appreciable difference in the speed of comparison. However, both of these are unpleasantly slow - ~300ms per selection change - particularly given that the dates made available to the sliders within the UI are predicated entirely on the results of this query, so user interaction has to halt in some fashion. Is there a (very) significantly faster way to do this? Edit: May not have been clear enough - order objects are materialized from SQL data at launch-time and these queries are performed later, in a secondary window of the overall application. SQL is irrelevant to the specifics of this question; this is a LINQ-to-Objects question.

Original source