[英]C# Finding an element in a List
假设我有以下C#代码
var my_list = new List<string>();
// Filling the list with tons of sentences.
string sentence = Console.ReadLine();
下列任何一项之间有什么区别?
bool c1 = my_list.Contains(sentence);
bool c2 = my_list.Any(s => s == sentence);
我想象背后的纯算法并不完全相同。 但是我这边的实际区别是什么? 一种方法比另一种方法更快或更有效吗? 一种方法有时会返回true,另一种会返回false吗? 我应该考虑选择一种方法还是另一种方法? 还是纯粹由我决定并且在任何情况下都可以工作?
实际上,两者将以几乎相同的方式运行:迭代列表的项,并检查句子是否与任何列表元素匹配,复杂度约为O(n)
。 我会争辩List.Contains
因为这样做比较容易和自然,但这是完全优先的!
现在,如果您要在查找复杂性和速度方面寻求更快的速度,我建议使用HashSet<T>
。 一般来说,HashSets的查找约为O(1)
因为从理论上讲,散列函数应该是恒定时间的操作。 再次,只是一个建议:)
最受欢迎的答案并不完全正确(这是大O并不总是有效的原因)。 在这种情况下,任何方法都会比包含方法慢(大约两倍)。
任何人每次迭代都会有一个额外的调用,即您在列表中每个项目上指定的委托,而不必包含。 额外的通话会大大降低它的速度。
结果将是相同的,但是速度将有很大不同。
基准示例:
Stopwatch watch = new Stopwatch();
List<string> stringList = new List<string>();
for (int i = 0; i < 10000000; i++)
{
stringList.Add(i.ToString());
}
int t = 0;
watch.Start();
for (int i = 0; i < 1000000; i++)
if (stringList.Any(x => x == "29"))
t = i;
watch.Stop();
("Any takes: " + watch.ElapsedMilliseconds).Dump();
GC.Collect();
watch.Restart();
for (int i = 0; i < 1000000; i++)
if (stringList.Contains("29"))
t = i;
watch.Stop();
("Contains takes: " + watch.ElapsedMilliseconds).Dump();
结果:
Any takes: 481
Contains takes: 235
迭代的大小和数量不会影响%差异,Any总是较慢。
对于string
对象,没有区别,因为==
运算符只是调用String.Equals
。
但是,对于其他的对象,可能有差异==
和.Equals
-看的实施.Contains
,它将使用EqualityComparer<T>.Default
,其中挂钩到Equals(T)
为您的类实现,只要IEquatable<T>
(其中T
本身)。 在不重载==
,大多数类改为对==
使用引用比较,因为这是它们从Object
继承的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.