【问题标题】:Bool list check if every item in list is false布尔列表检查列表中的每个项目是否为假
【发布时间】:2014-05-02 08:00:56
【问题描述】:

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

【问题讨论】:

    标签: c# list boolean


    【解决方案1】:

    你可以使用LINQ'sAll方法:

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

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

    【讨论】:

    • 如果列表不是布尔值而是包含布尔值的类,有没有办法执行此操作?
    • @RyanN1220 lambda 变量“x”代表这里的对象。所以您只需要更改条件x.SomeBoolProperty == false!x.SomeBoolProperty
    【解决方案2】:

    您可以使用Enumerable.Any 它会在第一次匹配时找到满足条件。正如 Habib 所说的那样,最好将 Any 用作 Enumerable。对于 Empty 的 bool 列表,All 将返回 true。

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

    或使用Enumerable.All

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

    【讨论】:

    • +1,最好使用Any,因为Enumerable.All 将返回true 以获得一个空的布尔列表。
    • +1 这比 All() 执行得更好,因为它总是迭代整个列表;当它找到一个时它会停止
    • @AdrianCarneiro 嗯..?这对我来说没有意义。两者都很懒惰,在这种情况下需要查看相同数量的元素。
    • @user2864740, negated 只是为 Any 提供 bool 值的一种简单方式,考虑以下代码:List<bool> list = new List<bool>(); var b1 = list.All(r => r == false); var b2 = list.Any(r => r == false);,现在 b1 将是 trueb2是假的。只是Enumerable.All 在空列表上的行为不同。
    • 显然列表包含一些项目。这两个语句不一样。如果有任何项目等于true,则首先返回true,如果所有项目都等于@987654337,则返回true @.您需要在第一条语句上使用否定运算符。
    【解决方案3】:

    我同意使用IEnumerable.Any/All。但是,我不同意当前投票最多的答案(在撰写本文时这是错误的)以及 Any vs All 的几个相关 cmet。

    以下这些操作在语义上是等价的。请注意,否定应用在谓词内部和运算结果上。

    !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中相同的求值次数;在内部,对于序列实现而言,差异只是否定了对谓词和结果值的检查。

    【讨论】:

    • 如果列表不是布尔值而是包含布尔值的类,有没有办法执行此操作?
    • @RyanN1220 是的。 LINQ 的 IEnumerable 在这方面是灵活的,因为在许多情况下都接受一个函数(例如,某些提供程序有限制,例如 LINQ-to-EF)。 All/Any 函数采用可选的Func<T, bool>。在上面,f(x) 是一个“一些代码”(和/或一个函数),它接受 x 并返回一个布尔值。例如,给定var a = new [] { Tuple.Create(1, true), Tuple.Create(1, false) },则a.Any(x => x.Item2) 为真,a.All(x => x.Item2) 为假。
    【解决方案4】:

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

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

    我将ContainsIEnumerable.Any 进行了比较,Contains 的返回速度更快。在我的测试中,IEnumerable.All 的性能与IEnumerable.Any 相同,可能在后台对这两个功能使用了类似的算法。我还检查了IEnumerable.Exists,它的性能优于IEnumerable.AnyIEnumerable.All,但仍然比Contains 慢。

    在 10,000,000 个布尔条目列表中(我也尝试了 0 和 1 个条目,结果相似),我得出了以下指标:

    经过任何 = 95ms

    全部经过 = 88 毫秒

    经过 Exists = 27ms

    经过包含 = 17ms

    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&lt;bool&gt;

    【讨论】:

    • 不错的性能比较。在有许多解决方案的地方,性能优先。
    • 如果列表不是布尔值而是包含布尔值的类,有没有办法执行此操作?
    • “..因为它可以在第一次出现 true.. 时提前返回。”AllAny 都可以(并且确实如此)。虽然Contains 可能更快,但由于提前终止而不是更快。检查.NET Reference Source's IEnumerable.All 中的实现,正如我所料,它是惰性的,不会强制评估整个序列。
    • @user2864740 好点 - 谢谢!我将编辑 OP 以反映这一点。
    猜你喜欢
    • 1970-01-01
    • 2019-08-29
    • 2014-03-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-10
    • 1970-01-01
    • 2015-04-09
    相关资源
    最近更新 更多