检查两个枚举之间是否存在共同单个元素的最快方法

时间:2014-04-18 14:46:08

标签: c# .net linq

我正在编写一种方法,我希望能够根据订单中是否有一个或多个订购产品来过滤订单,这些产品存在于用户选择的产品中。目前我正在这样做:

SelectedProductIDs.Intersect(orderProductIDs).Any()

在每个订单上执行(数据库中总共约20,000个订单,并且预计会快速增长),其中SelectedProducts和orderProductIDs都是string []。我还试图为SelectedProductIDs和orderProductIDs使用预先生成的HashSets,但这在比较速度上没有明显差异。

然而,这两者都令人不快 - 每次选择更改约300毫秒 - 特别是假设UI中滑块可用的日期完全取决于此查询的结果,因此用户交互必须以某种方式停止。是否有(非常)明显更快的方法?

编辑:可能不够清楚 - 订单对象在启动时从SQL数据中实现,并且这些查询稍后在整个应用程序的辅助窗口中执行。 SQL与此问题的细节无关;这是一个LINQ-to-Objects问题。

2 个答案:

答案 0 :(得分:4)

LINQ intersect将根据输入值重建新的HashSet,无论您做什么,即使输入已经是HashSet。它的实现在内部改变了哈希集(这就是它避免产生重复值的方式)所以重要的是要复制输入序列,即使它已经是HashSet

您可以创建自己的Intersect方法来接受哈希集,而不是填充新的哈希集。尽管如此,为了避免变异,你必须选择基于行李的Intersect而不是基于集合的Intersect(即序列中的重复将全部产生)。显然,在你的情况下这不是问题:

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;
}

现在你可以写:

SelectedProductIDs.InsersectAll(orderProductIDs).Any();

每次都不需要重新构建hashset。

答案 1 :(得分:0)

听起来您正在将数据库中的所有值读入内存然后查询。如果您使用LINQ to EF,它会将LINQ查询转换为在数据库上运行的SQL查询,这可能会明显加快。