3

我需要根据客户在过去 x 个月内是否没有预订任何工作来过滤客户列表。在我的代码中,我有两个列表,一个是我的客户,另一个是从今天到 x 个月前过滤的工作列表,这个想法是根据他们没有出现在工作列表中的 ID 来过滤客户。我尝试了以下方法:

filteredClients.Where(n => jobsToSearch.Count(j => j.Client == n.ClientID) == 0).ToList();

但无论如何,我似乎得到了所有客户。我可以很容易地做一个 foreach 但这会严重减慢这个过程。如何有效地根据工作列表过滤客户列表?

4

3 回答 3

3

您做错的主要事情是您没有将结果分配回某事。这就是为什么您的原件似乎保留了所有客户。但是我们仍然可以在原来的基础上改进:

filteredClients = filteredClients.Where(n => !jobsToSearch.Any(j => j.Client == n.ClientId)).ToList();

这与您的.Count()解决方案之间的区别在于.Any(),一旦遇到第一个匹配项,就可以停止查看每个客户端的作业列表,因此它应该运行得更快一些。但我们还没有完成。通过将工作列表缩小到仅不同的客户,我们可以做得更好:

var badClients = jobsToSearch.Select(j => j.Client).Distinct().ToList();
filteredClients = filteredClients.Where(n => !badClients.Any(j => j == n.ClientId)).ToList();

使用HashSet可能会更好,它可以像字典一样进行 O(1) 查找。假设客户端 ID 是一个 int:

 var badClients = new HashSet<int>(jobsToSearch.Select(j => j.Client));
 filteredClients = filteredClients.Where(n => !badClients.Contains(n.ClientId)).ToList();

最后一个选项是否表现更好取决于有工作的客户数量......如果列表很短, .Distinct() 可能仍然会做得更好。

最后,我通常不建议.ToList()这样打电话。尽可能将实际实现 List、Array 或集合类型保存到最后一刻,并尽可能长时间地将其保留为 Enumerable。

于 2012-12-17T22:45:50.110 回答
1

您是否考虑过使用“groupby”?

没有检查语法和编写代码(havnt vs available atm):

var groupedJobs = jobsearch.GroupBy(job => job.Client);
var itemsWithJobs = filteredList.Where(item => groupedJobs.ContainsKey(item.ClientID));

明天早上我可以检查语法。

最大的优点是,您已经建立了一个字典,在其中搜索要快得多。比迭代列表。

于 2012-12-17T22:45:17.097 回答
0

过滤属于inIdList 的客户;

List1.Where(x=> IdList.Contains(x.ClientId));

过滤属于not inIdList 的客户;

List1.Where(x=> !IdList.Contains(x.ClientId));
于 2012-12-17T22:42:11.440 回答