where 子句的调用频率高于项计数



我有一个List<Order>,我正在尝试使用 LINQ 过滤它:

var grouped = from o in orders
  group o by o.OrderNumber into g
  select new { Id = g.Key, Orders = g };
var GroupedList = grouped.ToList();
int max = GroupedList.Count();
int count = 0;
var filtered =
    from g in GroupedList
    where IncrementProgress(max, ref count)
    select g.Id;
var filteredOrders = orders.Where(o => filtered.Contains(o.OrderNumber));

IncrementProgress内,我打印countmax调试输出。 max在我的测试 3500 中,我从 150000 的 count 中获得输出并且还在不断增加。

有人知道为什么吗?

PS:在我的生产代码中,有过滤器逻辑而不是IncrementProgress

更新:

这里是IncrementProgress -方法:

private bool IncrementProgress(int max, ref int count)
{
    Debug.WriteLine("Filtering {0} of {1}", ++count, max);
    return true;
}

这是因为 LINQ 是惰性的,filtered 不是集合 - 它是一个内存中查询,它只存储如何计算结果的信息,而不是结果本身。因此,每次使用 filtered 时都会再次对其进行评估,遍历GroupedList并再次检查where条件。

这意味着,where条件将被评估orders.Count() * GroupedList.Count()次。

ToList()调用添加到filtered以急切地评估它。

var filtered =
    (from g in GroupedList
     where IncrementProgress(max, ref count)
     select g.Id).ToList();

但是,由于您稍后仅在filtered上使用Contains,因此应使用HashSet<int>来存储结果。它将使Contains调用 O(1) 而不是 O(n),这应该会大大提高性能。

var filtered =
    new HashSet<int>(from g in GroupedList
                     where IncrementProgress(max, ref count)
                     select g.Id);
每次

枚举筛选的集合时都会执行LINQ查询,在每次调用 Include 方法时都会执行。

尝试将过滤后的变量声明为 (<LINQ Query>).ToArray() 。这将仅枚举查询一次。

抱歉格式不正确(手机)。希望对您有所帮助。

相关内容

  • 没有找到相关文章

最新更新