【问题标题】:C# best approach to check a value is exist in a List Several timesC# 检查值的最佳方法是否存在于列表中多次
【发布时间】:2021-03-03 15:49:10
【问题描述】:

我有整数列表,我想知道我的列表中存在一个值多次。

最好的方法是什么?

使用LookUpdictionaryHashMap 或...捕获数据?

例子:

List<int> samples = {5,4,6,2,1}
// if(2 exist in samples) do something ...
// if(3 exist in samples) do something ...
// if(5 exist in samples) do something ...
// if(8 exist in samples) do something ...
// if(13 exist in samples) do something ...
// if ....

【问题讨论】:

  • “几次” - 列表的内容会在两次测试之间改变吗?
  • 您可以使用HashSet&lt;int&gt;,但您可能会通过一些额外的细节/上下文得到更有意义的答案。
  • 否,列表内容未更改
  • 最简单的方法可能就是使用 .Contains({item}) if (samples.Contains(2)){ do something }
  • "best" 是上下文相关的; “几次”是多少次?一打:只需使用Contains。很多很多次,经常在一个紧密的循环中?您需要优化的数据结构,例如HashSet&lt;T&gt;,或者至少您希望对其进行排序并使用二项式搜索进行检查。当然,也取决于数值的实数;如果它真的只有 1,2,4,5,6 - 只需使用 switch 块:您只需要针对大量测试用例进行优化

标签: c# search


【解决方案1】:

您可以将它们存储在HashSet中,并使用O(1)检查值是否存在:

var unique = new HashSet<int>(){ 5,4,6,2,1};
var hasValue = unique.Contains(1);

然后检查:

if (unique.Contains(2)) 
    // do something ...

另外,HashSet&lt;T&gt; 防止存储重复,所以速度非常快。

更新:

List&lt;T&gt; 将使用 O(N) 进行搜索。为什么?因为 Big O Notation 应该考虑时间复杂度的最坏情况。假设我们有以下列表:

var numbers = new List<int> { 5, 4, 6, 2, 1 };

我们想找到号码1。所以List&lt;T&gt;Contains() 方法必须遍历整个数组,直到找到数字1。所以我们有O(N)

LinkedList&lt;T&gt; 将使用 O(N) 进行搜索。为什么?原因与List&lt;T&gt; 相同。但是,LinkedList&lt;T&gt; 在底层没有数组,它有一个类,该类具有指向下一个元素的指针,而下一个元素具有指向下一个元素的指针,依此类推。我们必须遍历所有元素才能找到一个项目。

HashSet&lt;T&gt; 将使用 O(1) 进行搜索。为什么?原因是 HashSet&lt;T&gt; 在底层不会遍历数组。它将运行内部方法InternalGetHashCode,该方法返回数组中数字的位置。 You can see the source code here.

另外还有一个关于How can hashset.contains be O(1) with this implementation?的很好的回答

【讨论】:

  • 谢谢@stepUp,你能告诉我为什么不建议使用字典吗?还是别的什么?
  • @Amir133 因为字典存储了一个键/值对,而您在这里只需要一个键 - 而不是一个值,HashSet&lt;T&gt; 可以为您完成
  • @Amir133 Dictionary&lt;TKey, TValue&gt; 如果已经有要添加的密钥,则可以抛出异常。此外,使用Dictionary&lt;TKey, TValue&gt;,您必须存储TValue,但您没有必要。
  • @Amir133 List&lt;T&gt;LinkedList&lt;T&gt; 将搜索 O(N)
  • 谢谢@StepUp,你的回答对我来说已经足够了,但如果可以的话,给观众更多的解释。
【解决方案2】:

这取决于您所说的最佳。如果您使用的是列表,则可以使用 Exists() 方法。

if(samples.Exists(value => value == valueToCheck)){
    //Do work
}

【讨论】:

  • 可以告诉我Exists的顺序
  • Exists 不是这样工作的。它需要一个Predicate&lt;T&gt;,而不是一个值。
  • 搜索列表效率低下。除非你有一个玩具应用程序,否则你不应该使用具有 O(n) 时间复杂度的数据结构,即一个数组(或动态版本,一个列表)来进行查找。
  • 更新了答案以反映这一点。谢谢。
  • 即使有更新,也只需使用Contains()...它们都是 O(n)。 Exists() 除了在简单的List&lt;int&gt; 上使用时变得更复杂之外,在这里没有任何好处。显然,这里甚至不应该使用列表,但这是一个不同的论点。
猜你喜欢
  • 1970-01-01
  • 2022-06-06
  • 2018-11-03
  • 2017-08-26
  • 2015-01-10
  • 1970-01-01
  • 1970-01-01
  • 2012-08-29
  • 2019-10-03
相关资源
最近更新 更多