2016-12-15 48 views
3

我有一個IEnumerable,其中T是一個複雜的對象。我需要檢查列表中是否有5個或更多項目與lambda表達式匹配。目前我使用的是這樣的:檢查IEnumerable <T>有5個或更多的匹配

if(myList.Count(c=> c.PropertyX == desiredX && c.Y != undesiredY) >= 5)... 

不過,我myList中成長爲包含10K +對象這將成爲一個巨大的瓶頸,並很可能會找到一個匹配的前100項以上(但我可以」做出這個假設)。

我該如何儘可能有效地做到這一點。

+0

謝謝所有 - 從未使用跳過所有我的編程年...不是我有一個理由! –

+0

你是否真的想得到這五個,並與他們做些什麼,或者一旦有五場比賽你會處理所有事情?我注意到,在一些答案中,它檢查它們是否存在,但是將它們有效地拋棄,這意味着如果你需要它們,那麼你可能會重新做出謂詞,如果你可能檢查了很多對象,那麼效率可能不是很高... – Chris

+0

I抓取我目前想要使用的所有對象(500 - 10K對象)的列表。然後我需要檢查該列表以確保列表中每個項目類型至少有5個。如果沒有,我讓用戶知道這個集合沒有X類型的最小數量。然後我回到與更大的集合一起工作。 –

回答

3

可以使用Where過濾,然後Skip前4場比賽,並使用Any一旦它擊中第5比賽將停止迭代。少於5個匹配的情況仍然需要迭代整個列表。

if(myList.Where(c=> c.PropertyX == desiredX && c.Y != undesiredY).Skip(4).Any()) 
+0

工程很棒。將此方法的CPU時間從5%減少到1.5%。仍然需要找到一種更高效的方法,但現在這種方法仍然有效。 –

+1

如果你想讓它更高效,你可能不想使用linq。您在上面的評論中說,您正在檢查每個項目類型中至少有五項,這表明您正在多次執行此操作,這意味着需要重複迭代這些啓動對象。你可能會更好,只是在列表中列出並保存每一件你感興趣的東西,這樣你就可以在一次迭代中完成所有的檢查,而多次使用this/skip/any代碼將迭代列表對於每一個(直到滿足條件)。 – Chris

+0

@Chris假定列表內容不會改變,只需將「Any」調用的結果賦值給一個變量即可重用。 – juharr

1

您可以使用Skip 4個元素並檢查您的集合是否有其他元素。這樣你就不會計算集合中的全部元素。

var result = myList.Where(c=>c.PropertyX == desiredX && c.Y != undesiredY); 

if(result.Skip(4).Any()) 
{ 
    //has >= 5 elements. 
} 
+1

這確保有超過5個,而不是5個或更多。 – juharr

+0

@juharr是的,我沒有看到他想要> =,感謝提及它。 – mybirthname

2

如何使用一個普通的老for循環?:好像列表迭代

int count = 0; 
for (int i = 0; i < myList.Count; ++i) 
{ 
    if (myList[i].PropertyX == desiredX && myList[i].Y != undesiredY) 
     count++; 

    if (count == 5) 
     break; 
} 

這應該是幾乎一樣快,因爲它得到在單個線程。既然你不能在列表中列出這些項目的任何假設,算法的時間複雜度將不會比O(n)更好,其中n是列表中項目的數量,即在最壞的情況下您可能需要遍歷整個列表。並沒有更快的方式遍歷列表比使用for循環,我知道:)

+0

我想到了這個 - 如果它需要比'Skip'更快的速度,我會回來嘗試一下。 –

+0

'c'是什麼?你是否遺漏了'var c = myList [i];'? – juharr

+0

顯然:)我編輯了我的答案。 – mm8