2016-06-10 82 views
1

我有一个对象列表,其中的对象有一个Guid Id属性。检查Hashset中是否存在对象的单一属性值列表

我也有一个Hashset包含一堆Guid。

检查列表中的每个对象Guid是否存在于Hashset中的最快方法是什么,然后更新列表中Object的另一个属性(如果存在)?如果需要,我可以将Hashset更改为其他数据类型,但列表必须保持不变。

这里的类/枚举

public class Test 
{ 
public Guid Id {get; set;} 
public bool IsResponded {get; set;} 
} 

var clientResponses = new HashSet<Guid>(); 

var testRecords = new List<Test>(); 

这是我目前正在做

foreach (var test in testRecords) 
    { 
     if (clientResponses.Contains(test.Id)) 
      test.IsResponded = true; 
    } 
+0

“最快的方式”是指从耗时编码的角度,还是从应用程序的性能角度? –

+5

这似乎是对我来说最好的方法。一个更好的问题是你的性能要求到底是什么,这是否符合他们的要求?如果确实如此,则无需尝试对其进行优化。 – juharr

+0

首先你可以写'test.IsResponded = clientResponses.Contains(test.Id)'。除此之外,我认为这是最好的解决方案。 – Toxantron

回答

-1

你可以这样做

foreach (var test in testRecords) 
{ 
    if (clientResponses.Remove(test.Id)) 
     test.IsResponded = true; 
} 

,或者更简单地

foreach (var test in testRecords) 
{ 
    test.IsResponded = clientResponses.Remove(test.Id); 
} 

每个找到的值都从HashSet中删除,因此每次下一次迭代都会更快。当然,它只适用于大量的数据。此外,有必要重新创建一个HashSet。

你也可以试试这个优化(这是假设性IsResponded都默认为false)

foreach (var test in testRecords) 
{ 
    if (clientResponses.Remove(test.Id)) 
    { 
     test.IsResponded = true; 
     if (clientResponses.Count == 0) 
      break; // the remaining IsResponded values will remain unchanged 
    } 
} 

这种方法是有利的testRecords集合的大小比HashSet的大小显著较大,很有可能HashSet中的所有值都与此集合中的值一致。在查找全部的情况下,没有理由继续迭代该集合。所以,打破循环。

+0

你正在销毁他的HashSet没有真正的收益,他可能需要HashSet完成更新他的清单后。至于性能方面的考虑,Contains在HashSet上已经是O(1)操作。此外,删除是一个O(1)操作,因此每次删除后应该加快的陈述不具有真正的优点。 –

+0

@AnthonyPegram - 我提到需要重新创建HashSet。我同意,只有在完全匹配并且在循环中断后取消所有ID之后才有利。 –