简体   繁体   中英

Combination of conditional statements

I have 2 sets of 3 conditions each. Let a,b,c be one set of conditions and x,y,z be the other set. I need to evaluate the following

if(a && x)
..... 
else if(a && y) 
..... 
else if(a && z)
.....

In the same way 3 conditions with b and 3 with c.

What is the best way to evaluate the conditions without writing all the combinations?

Update :

I am making a game in Unity. The conditions a,b,c check whether the x position of the player is within a certain range compared to a ball's position and conditions x,y,z do the same for y position. Based on the correct condition(from the combination ax,ay,az,bx,by,bz,cx,cy,cz) one animation state(out of 9) is selected. So each condition would produce a different result.

Update : I ended up making two functions that evaluate the two sets of conditions and each returns an enum on which bitwise OR is done to get the final state.

My first thought would be to at least test the first group of conditions first, and then test the second group of conditions afterwards. While this is not an answer that avoids writing all nine if statements, you will on average reduce the amount of if statements being checked.

if (a) 
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}
else if (b)
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}
else if (c)
{
    if (x) { }
    else if (y) { }
    else if (z) { }
}

This is one way of doing it using Linq expressions, Linq expressions is a way to define expressions dynamically where you can do multiple operations on them. i used here a fake conditional expression that takes a number as an argument just for the sake of demonstration. first define each condition in a method or directly within you code. then put all those into arrays, each conditions set to an array. then two foreach that executes the expressions.

int num = 20;

        ConditionalExpression[] firstSet = { ExpressionA(num), ExpressionB(num), ExpressionC(num) };
        ConditionalExpression[] secondSet = { ExpressionX(num), ExpressionY(num), ExpressionZ(num) };

        foreach(var firstSetExpression in firstSet)
            foreach (var secondSetExpression in secondSet)
            {
                var result1 = Expression.Lambda<Func<bool>>(firstSetExpression.Test).Compile();
                var result2 = Expression.Lambda<Func<bool>>(secondSetExpression.Test).Compile();

                if (result1.Invoke() && result2.Invoke())
                { 
                    // do your thing here 
                }
            }

Where you define expressions for each condition within a method, for example like this:

private static ConditionalExpression ExpressionA(int num)
        {
             return Expression.Condition(
                          Expression.Constant(num > 10),
                          Expression.Constant("num is greater than 10"),
                          Expression.Constant("num is smaller than 10")
                        );
        }

this can be even optimized in many ways, but only to get you started.

Update: This is another way for who dont like to compile at runtime. using delegates:

Func<int, bool>[] firstSet = new Func<int,bool> [] { ExpressionA(), ExpressionA(), ExpressionA() };
            Func<int, bool>[] secondSet = new Func<int, bool>[] { ExpressionA(), ExpressionA(), ExpressionA() };

            foreach(var firstSetExpression in firstSet)
                foreach (var secondSetExpression in secondSet)
                {
                    if (firstSetExpression.Invoke(20) && secondSetExpression.Invoke(20))
                    { 
                        // do your thing here 
                    }
                }
...
...
...

private static Func<int, bool> ExpressionA()
        {
             return (x) => x > 10;
        }

Good Luck.

  1. Generate all possible combinations. Since you deal with Booleans, each gives you 2 options. Then the simplest possible combination of 2 bools results to 2 x 2 = 4 combinations. Generally saying, K = 2^n, where n represent number of booleans you deal with.

Would I be you, I would stick to Tuple<bool, bool, bool> and nested for(var i = 0; i < 2; i++) cycles (for n parameters n cycles needed).

  1. Then I would feed a list of Tuple<Predicate<Tuple<bool, bool, bool>>, Action> which pairs predicate with callback that should trigger when predicates equals true.

  2. Rest could be achieved with Linq. Something alike possibleCombinationsList.Select(tripleOfBooleans => predicatesAndCallbacksList.Single(predicateAndCallback => predicateAndCallback.Item1(tripleOfBooleans) == true)).Sinle().Item2();

Have fun.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM