C# 优雅地确定是否有多个布尔值为“真”

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/377990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 01:12:35  来源:igfitidea点击:

Elegantly determine if more than one boolean is "true"

c#hammingweight

提问by Ola Tuvesson

I have a set of five boolean values. If more than one of these are true I want to excecute a particular function. What is the most elegant way you can think of that would allow me to check this condition in a single if() statement? Target language is C# but I'm interested in solutions in other languages as well (as long as we're not talking about specific built-in functions).

我有一组五个布尔值。如果其中不止一个是真的,我想执行一个特定的功能。您能想到的最优雅的方法是什么,让我可以在单个 if() 语句中检查此条件?目标语言是 C#,但我也对其他语言的解决方案感兴趣(只要我们不讨论特定的内置函数)。

One interesting option is to store the booleans in a byte, do a right shift and compare with the original byte. Something like if(myByte && (myByte >> 1))But this would require converting the separate booleans to a byte (via a bitArray?) and that seems a bit (pun intended) clumsy... [edit]Sorry, that should have beenif(myByte & (myByte - 1))[/edit]

一个有趣的选择是将布尔值存储在一个字节中,右移并与原始字节进行比较。类似的东西if(myByte && (myByte >> 1))但这需要将单独的布尔值转换为一个字节(通过 bitArray?),这似乎有点(双关语)笨拙...... [edit]对不起,应该是if(myByte & (myByte - 1))[/edit]

Note: This is of course very close to the classical "population count", "sideways addition" or "Hamming weight" programming problem - but not quite the same. I don't need to know how many of the bits are set, only if it is more than one. My hope is that there is a much simpler way to accomplish this.

注意:这当然非常接近经典的“人口计数”、“横向加法”或“汉明权”编程问题——但并不完全相同。我不需要知道设置了多少位,仅当它多于一位时。我希望有一种更简单的方法来实现这一点。

采纳答案by Charles Bretana

How about

怎么样

  if ((bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + 
      (bool4? 1:0) + (bool5? 1:0) > 1)
      // do something

or a generalized method would be...

或者一个通用的方法是......

   public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    {
       int trueCnt = 0;
       foreach(bool b in bools)
          if (b && (++trueCnt > threshold)) 
              return true;
       return false;          
    } 

or using LINQ as suggested by other answers:

或按照其他答案的建议使用 LINQ:

    public bool ExceedsThreshold(int threshold, IEnumerable<bool> bools)
    { return bools.Count(b => b) > threshold; }

EDIT (to add Joel Coehoorn suggestion: (in .Net 2.x and later)

编辑(添加 Joel Coehoorn 建议:(在 .Net 2.x 及更高版本中)

    public void ExceedsThreshold<T>(int threshold, 
                      Action<T> action, T parameter, 
                      IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(parameter); }

or in .Net 3.5 and later:

或在 .Net 3.5 及更高版本中:

    public void ExceedsThreshold(int threshold, 
            Action action, IEnumerable<bool> bools)
    { if (ExceedsThreshold(threshold, bools)) action(); }

or as an extension to IEnumerable<bool>

或作为扩展 IEnumerable<bool>

  public static class IEnumerableExtensions
  {
      public static bool ExceedsThreshold<T> 
         (this IEnumerable<bool> bools, int threshold)
      { return bools.Count(b => b) > threshold; }
  }

usage would then be:

用法将是:

  var bools = new [] {true, true, false, false, false, false, true};
  if (bools.ExceedsThreshold(3))
      // code to execute  ...

回答by recursive

I would just cast them to ints and sum.

我只是将它们转换为整数和总和。

Unless you're in a super tight inner loop, that has the benefit of being easy to understand.

除非您处于非常紧密的内部循环中,否则这样做的好处是易于理解。

回答by faulty

if you mean more than or equal to one boolean equals to true, you could do it like

如果你的意思是多于或等于一个布尔值等于真,你可以这样做

if (bool1 || bool2 || bool3 || bool4 || bool5)

If you need more than one (2 and above) booleans equal to true, you can try

如果您需要多个(2 个及以上)等于 true 的布尔值,您可以尝试

int counter = 0;
if (bool1) counter++;
if (bool2) counter++;
if (bool3) counter++;
if (bool4) counter++;
if (bool5) counter++;
if (counter >= 2) //More than 1 boolean is true

回答by Victor

from the top of my head, a quick approach for this specific example; you could convert the bool to an int (0 or 1). then loop through therm and add them up. if the result >= 2 then you can execute your function.

从我的头顶,这个特定示例的快速方法;您可以将 bool 转换为 int(0 或 1)。然后循环遍历它们并将它们相加。如果结果 >= 2 那么你可以执行你的函数。

回答by Bork Blatt

In most languages true is equivalent to a non-zero value while false is zero. I don't have exact syntax for you, but in pseudo code, what about:

在大多数语言中,true 等价于非零值,而 false 为零。我没有确切的语法给你,但在伪代码中,怎么样:

if ((bool1 * 1) + (bool2 * 1) + (bool3 * 1) > 2)
{
    //statements here
}

回答by frankodwyer

Casting to ints and summing should work, but it's a bit ugly and in some languages may not be possible.

转换为整数和求和应该可以工作,但它有点难看,并且在某些语言中可能是不可能的。

How about something like

怎么样的东西

int count = (bool1? 1:0) + (bool2? 1:0) + (bool3? 1:0) + (bool4? 1:0) + (bool5? 1:0);

Or if you don't care about space, you could just precompute the truth table and use the bools as indices:

或者,如果您不关心空间,则可以预先计算真值表并将布尔值用作索引:

if (morethanone[bool1][bool2][bool3][bool4][bool5]) {
 ... do something ...
}

回答by John Sonmez

I would do something like this, using the params argument.

我会做这样的事情,使用 params 参数。

        public void YourFunction()
        {
            if(AtLeast2AreTrue(b1, b2, b3, b4, b5))
            {
                // do stuff
            }
        }

        private bool AtLeast2AreTrue(params bool[] values)
        {
            int trueCount = 0;
            for(int index = 0; index < values.Length || trueCount >= 2; index++)
            {
                if(values[index])
                    trueCount++;
            }

            return trueCount > 2;

        }

回答by Vilx-

Not exactly pretty... but here's another way to do it:

不是很漂亮……但这是另一种方法:

if (
    (a && (b || c || d || e)) ||
    (b && (c || d || e)) ||
    (c && (d || e)) ||
    (d && e)
)

回答by rp.

I'd write a function to receive any number of boolean values. It would return the number of those values that are true. Check the result for the number of values you need to be positive to do something.

我会编写一个函数来接收任意数量的布尔值。它将返回那些为真值的数量。检查结果中您需要肯定的值数量才能做某事。

Work harder to make it clear, not clever!

努力说清楚,而不是聪明!

private int CountTrues( params bool[] booleans )
{
    int result = 0;
    foreach ( bool b in booleans )
    {
        if ( b ) result++;
    }

    return result;
}

回答by AndreasN

if (NumberOfTrue(new List<bool> { bool1, bool2, bool3, bool4 }) >= 2)
{
    // do stuff
}

int NumberOfTrue(IEnumerable<bool> bools)
{
    return bools.Count(b => b);
}