Shyam
Shyam

Reputation: 37

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.

Upvotes: 0

Views: 1713

Answers (3)

RaniDevpr
RaniDevpr

Reputation: 410

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.

Upvotes: 1

Zazaeil
Zazaeil

Reputation: 4109

  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.

Upvotes: 1

Oystein
Oystein

Reputation: 1322

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) { }
}

Upvotes: 2

Related Questions