Bool list check if every item in list is false

后端 未结 4 670
轮回少年
轮回少年 2020-12-18 18:28

I have a List with lots of values. What is the most efficient way to check if every single item in the list equals false?

相关标签:
4条回答
  • 2020-12-18 18:48

    You can use Enumerable.Any it will find satisfy the condition on first match. As Habib rightly said better to use Any as Enumerable.All would return true for an Empty list of bool.

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

    OR use Enumerable.All

    lst.All(c=> c == false);
    
    0 讨论(0)
  • 2020-12-18 18:49

    You can use LINQ's All method:

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

    This will return false immediately if it finds a value that equals to true.

    0 讨论(0)
  • 2020-12-18 18:52

    I agree with the use of IEnumerable.Any/All. However, I disagree with the currently most-voted answer (which was wrong at the time of writing this) and several of the associated comments of Any vs All.

    These following operations are equivalent semantically. Note that the negations are applied both inside, on the predicate, and on the result of the operation.

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

    Now, in this case we are thus looking for:

    If it is not the case that there is any true value.

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

    Or,

    It is the case that every value is not true.

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

    There is nothing special for empty lists the result is the same: e.g. !empty.Any(..) is false, as is empty.All(..) and the above equivalence relation remains valid.

    In addition, both forms are lazily evaluated and require the same number of evaluations in LINQ To Objects; internally the difference, for a sequence implementation, is merely negating the check on the predicate and the result value.

    0 讨论(0)
  • 2020-12-18 18:57

    A significantly faster solution, not mentioned here, is using Contains

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

    I have compared Contains against IEnumerable.Any and Contains returns faster. In my tests IEnumerable.All performed the same as IEnumerable.Any, perhaps a similar algorithm is used for both these functions under the hood. I also checked IEnumerable.Exists which performed better than IEnumerable.Any and IEnumerable.All, but was still slower than Contains.

    Of a list of 10,000,000 bool entries (I also tried 0 and 1 entries, with similar results), I came up with the following metrics:

    Elapsed via Any = 95ms

    Elapsed via All = 88ms

    Elapsed via Exists = 27ms

    Elapsed via Contains = 17ms

    Contains is ~5.59x faster than Any!

    Tested with the following code:

    // 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);
    


    Note this will only work with types where type can only have two states (i.e. it won't work variables of >2 states, such as Nullable<bool>)

    0 讨论(0)
提交回复
热议问题