我要求根据客户列表在过去x个月内没有预订任何作业来过滤客户列表。在我的代码中,我有两个列表,一个是我的客户端,另一个是今天和x个月之前过滤的作业列表,其目的是根据客户列表中未显示的ID过滤客户端。我尝试了以下方法:
filteredClients.Where(n => jobsToSearch.Count(j => j.Client == n.ClientID) == 0).ToList();
但我似乎得到了所有客户。我可以很容易地做一个foreach但这会严重减慢这个过程。如何有效地根据作业列表过滤客户列表?
答案 0 :(得分: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)查找像Dcitionary。假设客户端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。
答案 1 :(得分:1)
没有检查语法和编写代码(havnt vs available atm):
var groupedJobs = jobsearch.GroupBy(job => job.Client);
var itemsWithJobs = filteredList.Where(item => groupedJobs.ContainsKey(item.ClientID));
我明天早上可以查看语法。
最大的优点是,你已经建立了一个Dictonary,它在搜索速度要快得多。而不是迭代列表。
答案 2 :(得分:0)
过滤in
IdList;
List1.Where(x=> IdList.Contains(x.ClientId));
过滤not in
IdList;
List1.Where(x=> !IdList.Contains(x.ClientId));