2017-06-13 82 views
2

我在檢查一個列表是否有一個元素的源和目標已經在列表中。如果沒有,我將這個元素添加到列表中。我這樣做:更快版本的LINQ .Any()和.Count()

if (!objectToSerialize.elements 
     .Any(x => x.data.source == edgetoAdd.data.source && 
       x.data.target == edgetoAdd.data.target)) 
     objectToSerialize.elements.Add(edgetoAdd); 

這個工程,但非常緩慢。有沒有辦法讓這部分更快? Any()Count有更快的實施嗎?提前致謝。

+0

你能之所以不會有循環在所有項目?例如,你可以將它們粘貼在一個字典中,其中'source'和'target'組成了快速查找的關鍵字,但是否可行取決於你的數據結構是什麼樣子以及你想要做什麼。僅僅爲這個代碼片段提供優化的相關提示幾乎是不可能的。請閱讀[問]並正確解釋你想要做什麼,包括展示[mcve]。 – CodeCaster

+0

使用不同的數據結構。也許是一個關於源和目標散列的字典。 – Steve

+0

@Steve該值的標識基於源和目標*,而不僅僅是目標,因此通過將源設置爲關鍵字來僅使用源作爲標識將是錯誤的。 – Servy

回答

10

對於某些T,您可以預先將數據索引爲HashSet<T>。因爲你在比較兩個值,一個元組可能會有所幫助:

var existingValues = new HashSet<(string,string)>(
    objectToSerialize.elements.Select(x => (x.data.source, x.data.target))); 

現在你可以有效地測試

existingValues.Contains((edgetoAdd.data.source, edgetoAdd.data.target)) 

。但!!建立索引不是免費的。這主要有助於如果你要測試很多值。如果你只添加一個,線性搜索可能是你最好的選擇。

請注意,您可以使用索引的方式與多個Add調用之間持續,的索引,但你也需要把它每次都記得.Add到索引中。您可以走捷徑測試/使用上的HashSet的.Add返回值增加對:一個更快的方法在所有的項目比...循環

if(existingValues.Add((edgetoAdd.data.source, edgetoAdd.data.target))) 
{ 
    // a new value, yay! 
    objectToSerialize.elements.Add(edgetoAdd); 
} 
+0

另一種選擇是將元素屬性本身更改爲HashSet? – mjwills