通过另一个筛选列表



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

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

但我似乎得到了所有的客户。我可以很容易地做前臂,但这严重减慢了这个过程。如何根据工作列表有效地筛选客户列表?

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

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)查找像Ddicional一样。假设客户端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。

您想过使用"groupby"吗?

不需要检查语法和编写代码(havnt与可用的atm):

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

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

最大的好处是,你已经构建了一个Dictionary,它在里面搜索要比在列表中迭代快得多。

过滤inIdList的客户端;

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

过滤not inIdList的客户端;

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

最新更新