Xaqron
Xaqron

Reputation: 30887

Simplifying a boolean logic

I have a function which should return true if all items pass the test. If only one item fails, then the function should return false. If there's no item in the collection the function should return false. Here is the code:

    private bool TestAll()
    {
        bool finalResult = false;
        bool itemResult = false;

        foreach (var item in Items)
        {
            itemResult = Test(item);

            if (!finalResult && itemResult)
                finalResult = true;
            else if (finalResult && !itemResult)
                finalResult = false;
        }

        return finalResult;
    }

How can I simplify the logic into one if statement using just one bool variable?

Upvotes: 0

Views: 1254

Answers (6)

pickypg
pickypg

Reputation: 22342

I realize this has been answered, and the shortest answer is the LINQ answer. Similar to others, but it requires a split second of thought:

private bool TestAll()
{
    var passed = true;

    foreach (var item in Items)
    {
        if ( ! Test(item))
        {
            passed = false;
        }
    }

    return passed && Items.Count != 0;
}

Upvotes: 1

Charles Lambert
Charles Lambert

Reputation: 5132

This will run all tests, return false if there are no tests, and return true only if all the tests pass:

private bool TestAll() {
  if (Items.Count == 0) return false;
  bool passed = true;
  foreach(var item in Items) {
    if (!Test(item))
      passed = false;
  }
  return passed;
}

Upvotes: 0

Matthew Abbott
Matthew Abbott

Reputation: 61617

You can use the IEnumerable.All extension method to test all items, which fails on the first instance of the Test method failing.

private bool TestAll()
{
    return Items.All(Test);
}

If you still need all items to be tested, you could probably use the AND assignment operator:

if (!Items.Any()) return false;

bool result = true;

foreach (var item in Items)
{
  result &= Test(item);
}

return result;

Upvotes: 6

temarsden
temarsden

Reputation: 332

private bool TestAll()
{
    foreach (var item in Items)
    {
        if(!(Test(item)) || Items.Count == 0)
        {
            return false;
        }
    }

return true;
}

Upvotes: 0

Jon
Jon

Reputation: 437904

If all the tests need to run, you can do it like this without LINQ:

private bool TestAll()
{
    var allTestsPassed = true;

    foreach (var item in Items)
    {
        allTestsPassed = Test(item) && allTestsPassed;
    }

    return allTestsPassed;
}

You can do it like this with LINQ:

private bool TestAll()
{
    return Items.Count(Test) == Items.Count();
}

Update: returning false if there are no tests to run

private bool TestAllWithoutLinq()
{
    if (Items.Count == 0) { // or something equivalent
        return false;
    }

    var allTestsPassed = true;

    foreach (var item in Items)
    {
        allTestsPassed = Test(item) && allTestsPassed;
    }

    return allTestsPassed;
}

private bool TestAllWithLinq()
{
    return Items.Any() && Items.Count(Test) == Items.Count();
}

Upvotes: 2

JaredPar
JaredPar

Reputation: 755587

Seems like an odd requirement that it should return false if only one item fails. Am I reading the question correctly? If so you can use the following

private bool TestAll() {
  int failCount = 0;
  foreach (var item in Items) {
    if (!Test(item)) {
      failCount++;
    }
  }
  return failCount != 1;
}

Upvotes: 0

Related Questions