【问题标题】:Avoid to browse a list multiple time with linq, with dynamic conditions (filter)避免使用 linq 多次浏览列表,使用动态条件(过滤器)
【发布时间】:2013-01-18 08:02:22
【问题描述】:

我有一个包含Article 对象的列表。 这个对象的参数是

类别、描述、状态、类

用户可以使用他想要的组合过滤列表。仅描述,或类别 + 类,依此类推。

所以如果用户选择一个标准,我会得到一个 int >= 0,否则我会得到 -1。

例如,如果他选择使用StatusCategory 进行过滤,我会得到

FilterCategory = x,FilterDescription = -1,FilterStatus = y,FilterClass = -1

我过滤列表的方法如下:

if (FilterCategory != -1)
    list = list.Where(a => a.Category == FilterCategory);
if (FilterDescription != -1)
    list = list.Where(a => a.Description == FilterDescription);
if (FilterStatus != -1)
    list = list.Where(a => a.Status == FilterStatus);
if (FilterClass != -1)
    list = list.Where(a => a.Class == FilterClass);

这样,我必须对列表进行 4 次迭代,对于很多项目来说效率不高。我会浏览一次列表,然后在一个唯一的位置检查 4 个条件。但我不知道如何在特定条件下做到这一点!= -1。

谢谢

【问题讨论】:

  • Linq 是惰性的,因此您不会使用代码对列表进行 4 次迭代。直到您迭代它或使用必须像 CountMax 一样迭代它的 Linq 扩展,才会发生迭代。

标签: c# linq where


【解决方案1】:

正如 Juharr 在 cmets 中提到的,Linq 不会在调用您的 .Where 后立即对其进行评估。只有在调用ToList/ToArray/First/Single/foreach 时,它才会评估子句并自动组合您的过滤器。

【讨论】:

  • 如果我有一个左连接并且我使用 DefaultIfEmpty 怎么办?
  • 备注 该方法采用延迟执行的方式实现。立即返回值是一个对象,它存储了执行操作所需的所有信息。
【解决方案2】:
list = list.Where(a => (FilterCategory != -1 || a.Category == FilterCategory) && 
                                       (FilterDescription != -1 || a.Description == FilterDescription) &&
                                       (FilterStatus != -1 || a.Status == FilterStatus) &&
                                       (FilterClass != -1 || a.Class == FilterClass));

【讨论】:

    【解决方案3】:

    您可以执行一个 HUGE Where 查询,将您的所有条件移动到一个 Where 并注意到:

    if (FilterCategory != -1)
        list = list.Where(a => a.Category == FilterCategory);
    

    相当于:

    list = list.Where(a => FilterCategory == -1 || a.Category == FilterCategory);
    

    那么查询是:

    list = list.Where(a => (FilterCategory == -1 || a.Category == FilterCategory)
                        && (FilterDescription == -1 || a.Description == FilterDescription)
                        && (FilterStatus == -1 || a.Status == FilterStatus)
                        && (FilterClass == -1 || a.Class == FilterClass));
    

    但我真的怀疑它会提高你的枚举性能。

    【讨论】:

    • Downvote:这不会提高性能;它实际上会减慢您的性能,因为检查-1 将每个项目发生一次,而不是之前一次。 您将Where 调用堆叠在一起的原始解决方案是正确的,并且由于 LINQ 的延迟执行(正如 @juharr 的评论所解释的那样),因此只会对列表进行一次迭代。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多