2016-04-25 56 views
2

假設我有定義爲我的C#程序如下一類:的Linq - 查找一個List <>缺失值 - 非常低效

class MyClass 
{ 
    public string ID; 
    public int Val; 
    public DateTime StartDate; 
    public DateTime EndDate; 
} 

而且我在我的節目一個巨大的List<MyClass>,我需要檢查如果在該列表中,其中的任何值:

  1. 某一組標準被滿足(在該簡化示例中,假設Val != 0,但條件是基本上比這更復雜)
  2. 還有一個對應的值在列表中(ID的比賽)與StartDate等於這個電流值的EndDate

我當前的代碼如下:

var myTest = new List<MyClass>(); 

... populate myTest ... 

var expectDt1 = myTest 
        .Where(v => v.Val != 0) 
        .Select(v => new {ID = v.ID, EndDate = v.EndDate}); 

var dontExist = expectDt1 
        .Where(tst => 
         !myTest.Any(v => 
          v.ID.Equals(tst.ID) 
          && v.StartDate == tst.EndDate 
          ) 
         ); 

此代碼的工作,但它的運行速度慢得要命(我的列表中有許多成千上萬的條目)。有沒有更好的方法來做到這一點(分組或其他),這將使這種效率更高? (PS - 我知道我可以把它變成一個更簡化的Linq語句,而不需要變量中間變量expectedDt1,但這並沒有提高效率,所以我簡單地寫了這樣的話來讓我的問題更容易理解)

+0

也許你chosed一個壞的數據結構這一點。你能否提供關於有多少記錄的細節,很多!= 0,有多少個重複的ID等等? –

+1

我會嘗試將列表填入'Dictionary >',其中外部鍵的鍵是StartDate。然後你只需要用正確的startdate和TryGetValue()來獲取所有的ID。這一切都需要花費時間來設置,但沒有冗餘。 (實際上沒關係 - 這是對Servy在他的回答中提出的建議的模仿,我之前從未聽說過ToLookup)。 –

+2

@EdPlunkett而不是一個字典嵌套在另一個字典中,使用一個字典和一個具有多個參數的字典在時間和空間上都比較有效率。並且使用'ILookup'(這與'Dictionary'非常相似的結構使得代碼更加清晰,因爲它支持密鑰的重複值(這對我們來說很好),並允許我們傳遞一個不存在的密鑰 – Servy

回答

6

您將希望創建一個基於散列的查找結構來查找具有給定值的項目,而不是通過對每個項目的大型列表進行線性搜索。

var lookup = myTest.Where(ItemIsValid) 
    .ToLookup(item => new 
    { 
     item.ID, 
     Date = item.EndDate, 
    }); 

然後,你要通過你的其他集合,看看是否能夠在查找找到一個匹配:

var query = expectDt1.Where(item => !lookup[new {item.ID, Date = item.StartDate}].Any()); 
+0

現在就試試吧,謝謝Servy! –

+0

這是** SUPER **快!!! - 謝謝SOOO很多!!!! –

相關問題