2017-06-13 85 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