Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to optimize a large number of if-else if-else expressions

here is the some sample line of codes..

if(loc > 0 || cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built) {    
 /// Condition to checn all true
    return true;
} else if(loc < 0 || cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built) { 
   /////// 1 false other are true 

} else if(loc > 0 || cat < 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built) { 

}

How to handle these condition. if i have 5 statement. Then it must be almost 12+ condition one by one.. if i am checking all the 5 combinations its going to more lines of code do we have any better option to check all the conditions.

like image 428
M Arfan Avatar asked May 31 '17 07:05

M Arfan


3 Answers

5 conditions is 2**5, i.e. 32 combinations.

If you want to check for various combination, without repeating the tests, you can bit-shift the individual results and combine them for a switch statement. working with the numbers directly is succinct but not very readable

var loc=1,cat=0,price=0,jsBed=1,bedroom=0,jsbuilt=0,built=1;

let results=[loc > 0,cat > 0,price > 0,jsBed <= bedroom,jsbuilt >= built];
let bits=results.reduce( (accum,current,index)=>accum+(current<<index), 0);
switch(bits){
case 0: // none
 break;
case 3: // first two
 break;
case 4: // third one
 break;
}

modifying this to use constants would make the switch statement more readable

var loc=0,cat=1,price=0,jsBed=1,bedroom=0,jsbuilt=0,built=1;

const locBit=1<<0;
const catBit=1<<1;
const priceBit=1<<2;
const bedBit=1<<3;
const builtBit=1<<4;
let bits=( loc > 0 )*locBit |
         ( cat > 0 )*catBit |
         ( price > 0 )*priceBit |
         ( jsBed <= bedroom )*bedBit |
         ( jsbuilt >= built )*builtBit;
switch(bits){
  case 0:
      console.log("!loc,!cat,!price,!bed,!built");
      break;
  case catBit|locBit:
      console.log("loc,cat,!price,!bed>!built");
      break;
  default:
      console.log(bits);
}

you could use constants to help

like image 82
Mic Avatar answered Oct 13 '22 08:10

Mic


If you treat a boolean expression as an integer in javascript, it will evaluate to 0 (for false) or 1 (for true). So you could sum the conditions and then use a switch-case construct to check how many were true:

var numTrue = 
   (loc > 0) + (cat > 0) + (price > 0) + (jsBed <= bedroom) + (jsBuilt >= built);

switch(numTrue) {
    case 0:
        // do something if no condition is met
        break;
    case 1:
        // do something else if one condition is met
        break;
    // etc...
}
like image 31
Mureinik Avatar answered Oct 13 '22 09:10

Mureinik


You have condition that will never be met :

if(loc > 0 || cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built){    
    /// Condition to checn all true
    return true;
} else if(loc < 0 || cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built) { 
/////// 1 false other are true 

} else if(loc > 0 || cat < 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built) { 

}

Basically :

  • On the second else if, the condition cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built is useless ebcause already met in the first one. Since you use an else if they will have already enter in the first if. So the only one that matter is loc < 0.
  • Same for last elseif only cat < 0 is relevant.

So it can be rewritten to

if(loc > 0 || cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built){    
    /// Condition to checn all true
    return true;
} else if(loc < 0) { 
/////// 1 false other are true 

} else if(cat < 0) { 

}

This answer assume that the code provided is the one that you're trying to simplify and not a generic sample.

Note : I think you may have not written what you wanted to do, forgetting some AND instead of OR.

like image 4
Walfrat Avatar answered Oct 13 '22 10:10

Walfrat