2012-12-17 121 views
3

我有一個要求,根據過去x個月沒有任何工作預訂過濾客戶列表。在我的代碼中,我有兩個列表,一個是我的客戶端,另一個是今天和x個月前的過濾的作業列表,我們的想法是根據未出現在作業列表中的客戶端過濾客戶端。我嘗試了以下內容:通過另一個篩選列表

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

但是,我似乎無論如何都得到所有客戶端。我可以輕鬆做到這一點,但是這會嚴重拖慢整個過程。我怎樣纔能有效地過濾基於作業列表的客戶列表?

+0

是j.Client和n.ClientID整數嗎? –

+0

您確定'jobsToSearch'查詢是否正確?你的代碼看起來應該做你打算做的事情。如果它不優化也不會幫助你。 –

+0

你永遠不會把結果分配給任何東西。 '.Where()'返回一個新的序列。它不會修改現有的序列。 –

回答

3

你做錯的主要原因是你不會把結果賦給某個東西。這就是爲什麼你的原創似乎讓所有的客戶。但是,我們仍然可以提高原始:

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

這和你.Count()解決方案之間的不同之處在於.Any()能儘快停止尋找與每一個客戶的任務列表中,因爲它遇到的第一個對手,所以它應該運行快一點。但我們還沒有完成。通過使用HashSet,它可以使O(1)查找像Dcitionary

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

而且可能甚至更好:我們可以做的,甚至通過縮小的工作做得更好列表下降到僅不同的客戶。假設客戶端ID是一個i​​nt:

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

這是否最後選擇性能更好取決於有工作的客戶端數量......如果列表短,.Distinct()仍可能做的更好。

最後,我通常不建議像這樣調用.ToList()。儘可能地保存實際的List,Array或collection類型,直到最後一刻,並儘可能長時間保持爲Enumerable。

+0

我不會打擾任何類型的排序。理想情況下,'badClients'只會變成某種'O(1)'查找(通過「ToLookup」,「ToDictionary」或者只是實例化一個'HashSet')。否則,對於要測試的每個客戶端ID,「badClients.Any(j => j == n.ClientId)」可以是「O(n)」。 –

+1

絕對是一個哈希集合,因爲沒有數據:密鑰的存在就足夠了。 –

+1

事實上,我喜歡這一點,我會在答案中使用它:) –

0

要過濾的客戶是in IdList;

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

要過濾的客戶是not in IdList;

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

您是否想過使用「groupby」?

而不檢查語法和編寫代碼了我的心(havnt VS提供ATM):

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

我可以檢查語法明天早上。

最大的問題是,你已經建立了一個Dictonary,它的搜索速度要快得多。比遍歷列表。

+1

+1這是這個,而不是'GroupBy'使用'ToLookup'而不是'ContainsKey'只是'Contains'(編輯:如果具有重複ClientID的作業數量特別大,那麼你可以使用'var groupedJobs = new HashSet (jobsToSearch.Select(j => j.Client))'來避免構建分組集合因爲我們真正需要的是一個ClientID查找) –

+1

這個想法並不是放鬆信息,客戶完成了哪些工作。我認爲,當他需要知道是否有任何工作完成時,下一個要求是顯示一份工作清單或至少計數。但它沒有被問到...所以HashSet會是更好的答案......你是對的=) –

+0

爲了澄清,這個想法是過濾客戶名單,根據他們是否在一段時間內有任何工作,我不我不需要保留最後的工作列表我只需要一個過濾的客戶列表 – user1166905