Alternative for multiple if statements

2020-04-14 02:15发布

问题:

My code contains a lot of multiple if statements. Is there any other way to get rid of these statements. For example suppose I have the following conditions

if(t1 >= 1 && t2 == 0 && t3 == 0) $('div.b_class').fadeIn();
if(t1 == 0 && t2 >= 1 && t3 == 0) $('div.c_class').fadeIn();
if(t1 == 0 && t2 == 0 && t3 == 1) $('div.d_class').fadeIn();
if(t1 && t2 >= 1 && t3 == 0) $('div.b_class.c_class').fadeIn();
if(t1 && t3 >= 1&& t2 == 0) $('div.b_class.d_class').fadeIn();

Is there any way to simplify these statements?

回答1:

You could use a switch case structure with conditions inside like this :

switch(true)
{
 case (t1 >= 1 && t2 == 0 && t3 == 0) : $('div.b_class').fadeIn(); break;
 case (t1 == 0 && t2 >= 1 && t3 == 0) : $('div.c_class').fadeIn(); break;
 case (t1 == 0 && t2 == 0 && t3 == 1) : $('div.d_class').fadeIn(); break;
 case (t1 && t2 >= 1 && t3 == 0)      : $('div.b_class.c_class').fadeIn(); break;
 case (t1 && t3 >= 1&& t2 == 0)       : $('div.b_class.d_class').fadeIn(); break;
}


回答2:

This should work:

var selector = 'div';
if (t1) {
    selector += '.b_class';
}
if (t2) {
    selector += '.c_class';
}
if (t3) {
    selector += '.d_class';
}
$(selector).fadeIn();

It relies on the "truthy/falsy" values for tX (0 is falsy, 1-3 are truthy, see http://11heavens.com/falsy-and-truthy-in-javascript for further details on "truthy/falsy").

The only caveat to this approach is that it allows selector to be 'div.b_class.c_class.d_class' if t1, t2, and t3 are all non-zero.

If selector is not acceptable in this case, change the t3 conditional to if (t3 && !(t1 || t2)).

When the t3 conditional is modified to if (t3 && !(t1 || t2)), the only way selector can have d_class appended is if t3 is non-zero and both t1 and t2 are zero.

var selector = 'div';
if (t1) {
    selector += '.b_class';
}
if (t2) {
    selector += '.c_class';
}
if (t3 && !(t1 || t2)) { //modified conditional
    selector += '.d_class';
}
$(selector).fadeIn();

UPDATE:

The original answer was for what I suspected the OP actually intended (as the OP implies the code is hypothetical), so kudos to Juve for spotting that. To satisfy cbayram, this will duplicate the OP's logic (though I'm not sure if you could call this "simplified", as it only removes one if comparison and is substantially more difficult to read).

var selector = 'div';
if ((((t1 && !(t2 || t3)) || (t1 && t3) || (t1 && t2 && !t3))) && !(t1 && t2 && t3)) {
    selector += '.b_class';
}
if ((t2 && !(t1 || t3)) || (t1 && t2 && !t3)) {
    selector += '.c_class';
}
if ((t3 === 1 && !(t1 || t2)) || (t1 && t3 && !t2)) {
    selector += '.d_class';
}
if (selector === 'div') {
    selector = '';
}
$(selector).fadeIn();

Here's a fiddle of it in action: http://jsfiddle.net/dX7AK/



回答3:

OK, assuming you really have a lot of ifs and your ts are fixed integers, and the main goal is readability of your many, many "rules". Then you can try the following.

First I would make sure that all ts have a valid value and skip the undefined cases. If the variables t are real logic values rather than numbers I would also use only explicit rules (e.g., t1 == 0 instead of using >, <, >=, <=), esp. if the rules you want to implement are as diverse as those expressed in your if statements.

Then you could encode the logic using a numeric system, e.g., using decimals for good readability. For each t you use one decimal position of a the new "logic number" that encodes your logic:

111 means t1 == t2 == t1 == 1
201 means t1 == 2, t2 == 0, t3 == 1
etc.

The number is easily created from your t1,t2, and t3:

num = t1*100 + t2*10 + t3

The switch-case below implements your logic. It is an unfolded version of your if rules. By not allowing for multi value checks (via >=, etc.) we need to specify a rule for every combination you want to handle. This might increase the number or rules you have to specify but might also make your logic rules more readable and maintainable.

var getFadeInClass = function(t1,t2,t3) {
    // for the sake of shortness I use ".b" instead of ".b_class" etc.
    var num = t1*100 + t2*10 + t3

    switch(logic_state){
    case 100:; case 200:; case 300: return ".b"
    case  10:; case  20:; case  30: return ".c"

    case   1:                       return ".d"

    case 110:; case 120:; case 130:;
    case 210:; case 220:; case 230:;
    case 310:; case 320:; case 330: return ".b.c"

    case 101:; case 102:; case 103:;
    case 201:; case 202:; case 203:;
    case 301:; case 302:; case 303: return ".b.d"
}
return ""

}

You could also use Math or other kinds of test to reason on the numbers.

var x = t1*100 + t2*10 + t3
if ( x != 0 && x%100    == 0)  return "b"
if ( x != 0 && x%100%10 == 0)  return "c"
if ( x == 1 )                  return "d"

But I would prefer the switch-case because it reads more nicely. I hope this is what you wanted to achieve. :)

You can check out a running version of this decimal logic in this fiddle.

Cheers, Juve



回答4:

If t1, t2, and t3 are 0 to positive infinity, modified logic is a little condensed:

<!DOCTYPE html>
<html>
   <head>
      <script type="text/javascript">
        function orig(t1, t2, t3) {
            var hits = "";
            if(t1 >= 1 && t2 == 0 && t3 == 0) hits += 'div.b_class\n';
            if(t1 == 0 && t2 >= 1 && t3 == 0) hits += 'div.c_class\n'; 
            if(t1 == 0 && t2 == 0 && t3 == 1) hits += 'div.d_class\n';
            if(t1 && t2 >= 1 && t3 == 0) hits += 'div.b_class.c_class\n';
            if(t1 && t3 >= 1 && t2 == 0) hits += 'div.b_class.d_class\n';
            return hits;
        }
        function modified(t1, t2, t3) {
            var hits = "";
            if(t2 >= 1 && t3 == 0)
                hits += (t1 == 0)?'div.c_class\n':'div.b_class.c_class\n';
            if(t1 >= 1 && t2 == 0) 
                hits += (t3 == 0)?'div.b_class\n':'div.b_class.d_class\n';          
            if(t1 == 0 && t2 == 0 && t3 == 1)   
                hits += 'div.d_class\n';
            return hits;
        }

        function runTest() {
            for(var i = 0; i < 3; i++) {
                for(var j = 0; j < 3; j++) {
                    for(var k = 0; k < 3; k++) {                    
                        var o = orig(i, j, k);
                        var m = modified(i, j, k);
                        if(o != m)
                            console.info(o + " | " + m);
                        console.warn("t1="+i+", t2="+j+", t3="+k + ": " + ((o == m)?"PASS":"FAIL"));            
                    }       
                }       
            }       

        }
      </script>
   </head>
   <body onload="runTest()">
   </body>
</html>

In either case, this is a good way to test out your modification vs the original.