【问题标题】:Simplifying a boolean logic简化布尔逻辑
【发布时间】:2011-08-17 21:16:45
【问题描述】:

如果所有项目都通过测试,我有一个函数应该返回 true。如果只有一项失败,则该函数应返回 false。如果集合中没有项目,则该函数应返回 false。代码如下:

    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;
    }

如何仅使用一个bool 变量将逻辑简化为一个 if 语句?

【问题讨论】:

  • 是否需要运行所有测试,或者一旦其中一个出现false,您可以跳过其余的测试吗?
  • @Jon:所有测试都应该通过,即使一个或全部失败。这就是为什么我没有使用break
  • 顺便说一句,您发布的代码有问题:只要最后一个通过,如果任意数量的测试失败,它将返回 true

标签: c# logic boolean


【解决方案1】:

您可以使用IEnumerable.All 扩展方法来测试所有项目,这会在Test 方法失败的第一个实例上失败。

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

如果您仍然需要测试所有项目,您可以使用 AND 赋值运算符:

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

bool result = true;

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

return result;

【讨论】:

  • 这不会运行所有测试(MSDN:'一旦可以确定结果,源的枚举就停止了。'),正如所要求的那样。
  • 如果集合中没有项目,您的答案将返回 true,应该是 false
【解决方案2】:

如果所有的测试都需要运行,你可以在没有 LINQ 的情况下这样做:

private bool TestAll()
{
    var allTestsPassed = true;

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

    return allTestsPassed;
}

你可以用 LINQ 做这样的事情:

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

更新:如果没有要运行的测试,则返回 false

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();
}

【讨论】:

  • 问题是,如果Items集合中没有项目,它应该返回false
  • 你也可以Items.Any() && Items.All(Test)吗?它会首先在没有项目的情况下失败,但如果所有项目的结果为真,则通过?
  • @MatthewAbbott:任何涉及Enumerable.All 的解决方案都无法满足“无论如何都必须运行所有测试”的要求。
【解决方案3】:

我意识到这已经得到解答,最短的答案是 LINQ 答案。与其他人类似,但需要花点时间思考:

private bool TestAll()
{
    var passed = true;

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

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

【讨论】:

  • 您的解决方案没有为所有需要的项目调用Test 方法。
  • 刚看到第二条评论,你在我点击编辑时回复了:)。
【解决方案4】:

如果只有一个项目失败,它应该返回false 似乎是一个奇怪的要求。我是否正确阅读了这个问题?如果是这样,您可以使用以下

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

【讨论】:

    【解决方案5】:
    private bool TestAll()
    {
        foreach (var item in Items)
        {
            if(!(Test(item)) || Items.Count == 0)
            {
                return false;
            }
        }
    
    return true;
    }
    

    【讨论】:

      【解决方案6】:

      这将运行所有测试,如果没有测试则返回 false,仅当所有测试都通过时返回 true:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-05-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-02-02
        • 2012-07-27
        • 2011-09-30
        相关资源
        最近更新 更多