Bool列表检查列表中的每一项是否为假

本文关键字:列表 一项 是否 检查 Bool | 更新日期: 2023-09-27 17:53:16

我有一个有很多值的List<bool>。检查列表中每个项目是否都等于false的最有效方法是什么?

Bool列表检查列表中的每一项是否为假

您可以使用Enumerable.Any,它会在第一次匹配时发现满足条件。正如Habib正确地说的,最好使用Any作为Enumerable。对于bool类型的空列表,都将返回true。

!lst.Any(c=> c == true);

OR使用Enumerable。所有的

lst.All(c=> c == false);

这里没有提到的一个明显更快的解决方案是使用 Contains

if (!myList.Contains(true))
    // Great success - all values false! 

我比较了ContainsIEnumerable.AnyContains的回报更快。在我的测试中,IEnumerable.All的执行与IEnumerable.Any相同,也许这两个函数在底层使用了类似的算法。我还检查了IEnumerable.Exists,它的性能比IEnumerable.AnyIEnumerable.All好,但仍然比Contains慢。

对于一个包含10,000,000个bool条目的列表(我也尝试了0和1条目,结果类似),我提出了以下指标:

通过

运行>任何

= 95 ms

Elapsed via All = 88ms

Elapsed via Exists = 27ms

通过

运行>包含

= 17女士

Contains比Any快~5.59倍 !

用以下代码测试:

// setup initial vars
var myList = new List<bool>();
for (int x = 0; x < 10000000; x++)
    myList.Add(false);  
var containsAllFalse = false;
Stopwatch sw = new Stopwatch();
// start test
sw.Start();
containsAllFalse = !myList.Any(x => x);
sw.Stop();
// get result for Any
var timeAny = sw.ElapsedMilliseconds;
// reset variable state (just in case it affects anything)
containsAllFalse = false;   
// start test 2
sw.Restart();
containsAllFalse = myList.All(x => x == false);
sw.Stop();
// get result for All
var timeAll = sw.ElapsedMilliseconds;
// reset variable state (just in case it affects anything)
containsAllFalse = false;   
// start test 3
sw.Restart();
containsAllFalse = !myList.Exists(x => x == true);
sw.Stop();
// get result for All
var timeExists = sw.ElapsedMilliseconds;
// reset variable state (just in case it affects anything)
containsAllFalse = false;   
// start test 4
sw.Restart();   
containsAllFalse = !myList.Contains(true);          
sw.Stop();
// get result from Contains
var timeContains = sw.ElapsedMilliseconds;
// print results
var percentFaster = Math.Round((double)timeAny / timeContains, 2);
Console.WriteLine("Elapsed via Any = {0}ms", timeAny);
Console.WriteLine("Elapsed via All = {0}ms", timeAll);
Console.WriteLine("Elapsed via Exists = {0}ms", timeExists);
Console.WriteLine("Elapsed via Contains = {0}ms", timeContains);
Console.WriteLine("Contains is ~{0}x faster than Any!", percentFaster);


注意,这只适用于类型只能有两种状态的类型(也就是说,它不能工作>2状态的变量,比如Nullable<bool>)

我同意使用IEnumerable.Any/All。然而,我不同意目前投票最多的答案(在写这篇文章的时候是错误的)和一些任何对所有的相关评论。

下面这些操作在语义上是等价的。注意,在内部、谓词上和操作结果上都应用了否定

!l.Any(x => f(x))
l.All(x => !f(x))

现在,在这个例子中,我们正在寻找:

如果不是,则存在任何真值的情况。

!l.Any(x => x)  // f(x) = x == true

,

在这种情况下,每个值都不是为真。

l.All(x => !x)  // f'(x) = !f(x) = !(x == true)

对于空列表没有什么特别的,结果是相同的:例如!empty.Any(..)是假的,empty.All(..)也是假的,上述等价关系仍然有效。

此外,两个表单都是惰性求值的,并且在LINQ To Objects中需要相同的求值次数;在内部,对于序列实现,区别仅仅是对谓词和结果值的检查取反。

您可以使用LINQ's All方法:

list.All(x => x == false);

如果它找到一个等于true的值,它将立即返回false