4

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?

DrummerB
  • 39,814
  • 12
  • 105
  • 142
Alonso
  • 251
  • 2
  • 7
  • 11
  • 3
    You can group some, such as `t3 == 0`. – chris Oct 20 '12 at 00:35
  • @Ken Doesn't look like a simple switch case to me. – DrummerB Oct 20 '12 at 00:36
  • @Ken how is he supposed to switch cases on conditions which are not expressions? This is not a functional language with pattern matching :) – Jack Oct 20 '12 at 00:37
  • even if conditions can be grouped, how will group the $('div') statements? – Aniket Inge Oct 20 '12 at 00:38
  • the language mentioned here is the C language, i also think that the conditions can be easily simplified. – Ken Oct 20 '12 at 00:38
  • @Ken: as I said, this is NOT a functional language with pattern matching. – Jack Oct 20 '12 at 00:39
  • @Alonso Are you sure you meant `t1 && t2 >= 1` in your 4th `if`? That would be the same as `t1 != 0 && t2 >= 1` and judging from the other `if` statements I think you wanted `t1 >= 1 && t2 >= 1` (which is the same if your using unsigned integers of course). – DrummerB Oct 20 '12 at 00:40
  • at this point i don't know what this question is about ... also all this if can be better organized – Ken Oct 20 '12 at 00:40
  • 3
    what language is that ? why you put C in the tags ? I don't get the entire question. – Ken Oct 20 '12 at 00:41
  • @DrummerB i answered, but i don't think that the ideas are clear in this case. in C the equivalent to multiple if is the switch case statement, otherwise i don't know what we are talking about here. – Ken Oct 20 '12 at 00:43
  • Sorry, I mentioned the wrong programming language. It's not 'C', it's jQuery and @ken in this question only some logic need to be implemented. – Alonso Oct 20 '12 at 00:47
  • Jquery it's not a language ... maybe it's javascript. I'm not a javascript expert so i will leave this but honestly i don't know how you can deal with that in an efficient way especially with a language like javascript. – Ken Oct 20 '12 at 00:50
  • If you do decide to go with a switch statement, don't break out of the conditions and maintain your order until you've done some logic re-factoring. :) – cbayram Oct 20 '12 at 01:09
  • 2
    @Alonso what is safe to assume for t1, t2 and t3 values? Can we assume they are going to be integers? – cbayram Oct 20 '12 at 01:21
  • yes, they are inegers only wih values between 0 to 3 only and one more thing, i could have used if-else-if statement above, only one statement will be true at a time from the above statements – Alonso Oct 20 '12 at 05:25
  • @Alonso As you can see people are trying to guess a lot what you actually want to do. Next time, please try describe in more detail what you actually want to do and post more complete (runnable) pieces of code. Do not shorten your actual problem too much for the sake of the question. – Juve Oct 21 '12 at 08:54
  • will keep in mind from next time. – Alonso Oct 21 '12 at 15:33
  • @Alonso If you are happy with one of the answers then please mark it as accepted answer. – Juve Oct 23 '12 at 18:21

4 Answers4

5

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;
}
sdespont
  • 13,915
  • 9
  • 56
  • 97
1

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.

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

halfer
  • 19,824
  • 17
  • 99
  • 186
Juve
  • 10,584
  • 14
  • 63
  • 90
  • That `switch` statement hurts. – Bergi Oct 20 '12 at 21:31
  • I know, but he wrote that he has "a lot" of `if` statements. I assume he has some more complex logic (since his `t`s can take four different values). For a real four-valued logic you can't easily have a very short AND nice too read solution. You need to deal with all the different possibilities. – Juve Oct 20 '12 at 23:32
  • Still, you could have used fall-through in this case. – Bergi Oct 21 '12 at 10:29
  • Mmh, OK. I didn't think of it. Thanks for the hint! – Juve Oct 21 '12 at 15:46
  • Thanks Juve. Your answer deserves an upvote. Got an idea from your answer. – Alonso Oct 23 '12 at 19:26
1

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/

Community
  • 1
  • 1
pete
  • 24,141
  • 4
  • 37
  • 51
  • 1
    The right idea, but poor execution. This is not remotely the same logic as the original conditional logic. | div.d_class t1=0, t2=0, t3=2: FAIL | div.c_class t1=0, t2=1, t3=1: FAIL | div.c_class t1=0, t2=1, t3=2: FAIL | div.c_class t1=0, t2=2, t3=1: FAIL | div.c_class t1=0, t2=2, t3=2: FAIL div.b_class.d_class | div.b_class t1=1, t2=0, t3=1: FAIL div.b_class.d_class | div.b_class t1=1, t2=0, t3=2: FAIL | div.b_class.c_class t1=1, t2=1, t3=1: FAIL – cbayram Oct 21 '12 at 08:00
  • cont'd... | div.b_class.c_class t1=1, t2=1, t3=2: FAIL | div.b_class.c_class t1=1, t2=2, t3=1: FAIL | div.b_class.c_class t1=1, t2=2, t3=2: FAIL div.b_class.d_class | div.b_class t1=2, t2=0, t3=1: FAIL div.b_class.d_class | div.b_class t1=2, t2=0, t3=2: FAIL | div.b_class.c_class t1=2, t2=1, t3=1: FAIL | div.b_class.c_class t1=2, t2=1, t3=2: FAIL | div.b_class.c_class t1=2, t2=2, t3=1: FAIL | div.b_class.c_class t1=2, t2=2, t3=2: FAIL – cbayram Oct 21 '12 at 08:01
  • if(t1 == 0 && t2 == 0 && **t3 == 1**) $('div.d_class').fadeIn(); – cbayram Oct 21 '12 at 08:04
  • 1
    Exactly! This "simplyfing" solution does not do what Alonso describes. But maybe what Alonso intended ;-). – Juve Oct 21 '12 at 08:51
0

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.

cbayram
  • 2,259
  • 11
  • 9