Elegantly determine if more than one boolean is “t

2019-01-13 05:26发布

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).

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 been 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.

22条回答
Explosion°爆炸
2楼-- · 2019-01-13 05:49

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.

查看更多
3楼-- · 2019-01-13 05:49

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 ...
}
查看更多
smile是对你的礼貌
4楼-- · 2019-01-13 05:50

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.

查看更多
混吃等死
5楼-- · 2019-01-13 05:50

While I like LINQ, there are some holes in it, like this problem.

Doing a count is fine in general, but can become an issue when the items your counting take a while to calculate/retrieve.

The Any() extension method is fine if you just want to check for any, but if you want to check for at least there's no built in function that will do it and be lazy.

In the end, I wrote a function to return true if there are at least a certain number of items in the list.

public static bool AtLeast<T>(this IEnumerable<T> source, int number)
{
    if (source == null)
        throw new ArgumentNullException("source");

    int count = 0;
    using (IEnumerator<T> data = source.GetEnumerator())
        while (count < number && data.MoveNext())
        {
            count++;
        }
    return count == number;
}

To use:

var query = bools.Where(b => b).AtLeast(2);

This has the benefit of not needing to evaluate all the items before returning a result.

[Plug] My project, NExtension contains AtLeast, AtMost and overrides that allow you to mix in the predicate with the AtLeast/Most check. [/Plug]

查看更多
The star\"
6楼-- · 2019-01-13 05:50

I wanted to give a C++11 variadic template answer.

template< typename T>
T countBool(T v)
{
    return v;
}

template< typename T, typename... Args>
int countBool(T first, Args... args)
{
    int boolCount = 0;
    if ( first )
        boolCount++;
    boolCount += countBool( args... );
    return boolCount;
}

simply calling it as follows creates a rather elegant method of counting the number of bools.

if ( countBool( bool1, bool2, bool3 ) > 1 )
{
  ....
}
查看更多
啃猪蹄的小仙女
7楼-- · 2019-01-13 05:52

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

        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;

        }
查看更多
登录 后发表回答