如何优化大量的if-else if-else表达式

10

这里是一些示例代码行..

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

}

如何处理这些条件。 如果我有5个语句。那么几乎必须逐一检查12+个条件..如果我检查所有5种组合,将会导致更多的代码行数,我们是否有更好的选项来检查所有条件。


5
你在上面的三个检查中重复了最后三个,你可以只检查一次,并嵌套一个 if 语句来处理剩下的部分。 - James Gould
所以你想要一个包含所有变量可能性的if-elseif-else分支?price>0 || jsBed <= bedroom || jsBuilt >= built看起来是重复的。不确定你是否想要检查例如jsBed>bedroom - KarelG
1
你是想找到满足条件的总数吗?(第二个和第三个条件应该被视为相同的条件)还是根据满足的条件有不同的实现方式? - Alexandru Severin
2
根据评论,您希望使用AND &&代替OR || - Kruga
5个回答

13

如果你在 JavaScript 中将布尔表达式视为整数,它将评估为 0(对于 false)或 1(对于 true)。因此,您可以总结这些条件,然后使用 switch-case 结构来检查有多少是 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...
}

1
看起来很合理。我正在考虑一下。谢谢 @Mureinik - M Arfan
根据提供的信息,这是最佳解决方案之一,但如果有其他组合,请将它们添加到问题中。还有其他方法可以帮助解决问题。 - Rajesh
6
将 loc=0,cat=1 视为 loc=1,cat=0 进行处理。这并没有解决 OP 的例子,只是检查满足条件的总数。 - Alexandru Severin
2
实际上,我可能是错的,这可能是OP正在寻找的,尽管没有明确说明。 - Alexandru Severin
如果您想要检查特定的条件,请将测试移动一个增加的值,例如:var numTrue = (loc > 0) + ( (cat > 0) << 1) + ( (price > 0) << 2) + ( (jsBed <= bedroom) << 3) + ( (jsBuilt >= built) << 4); - Loufylouf

4
您有一个永远无法满足的条件:
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) { 

}

基本上:

  • 在第二个else if中,条件cat > 0 || price > 0 || jsBed <= bedroom || jsBuilt >= built是无用的,因为已经在第一个条件中满足了。由于您使用了else if,它们已经进入了第一个if中。所以唯一重要的是loc < 0
  • 最后一个elseif也是同样的情况,只有cat < 0是相关的。

因此,可以重写为

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

}

本回答假设提供的代码是您要简化的代码,而不是通用示例。

注意:我认为您可能没有写出您想要做的事情,忘记了一些AND而不是OR。


1
在我读完这个问题后,我也是这么想的:“这有很多无用的检查。” - Kevin
@Walfrat。我很感激你的努力。如果我的条件匹配,我只想返回true。一旦匹配,它将不会继续向前移动。因为我们知道在JavaScript中一旦返回true或false就会停止。谢谢。 - M Arfan
我认为这将减少检查,而条件保持不变。 - M Arfan

3

5个条件有2的5次方种组合,即32种。

如果您想检查各种组合而不重复测试,可以对单个结果进行位移并将它们组合成一个switch语句。 直接使用数字工作简洁但不太易读。

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;
}

使用常量修改此代码会使 switch 语句更易读

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

您可以使用常量来帮助。


1

编辑1:修改为JavaScript,不是Java。糟糕...

我不确定您是否想要查看所有组合,但您可以通过为每个可能的输出引入数字值来对它们进行分组。

具体来说,有5个变量和每个变量2个选项?我已经设置了一个用二进制表示的数字表格。如果每个(或某些)变量有> 2个选项,您必须使用数字(十进制)。您可以使用类似于二进制值的值

const locVal  = (loc > 0 ? 0x1 : 0x0) << 0;
const catVal  = (cat < 0 ? 0x1 : 0x0) << 1;
const priceVal= (price < 0 ? 0x1 : 0x0) << 2;
ect

所以您可以在一个方法中对它们进行分组:

function foo(trueCond, level) {
    return (trueCond ? 0b1 : 0b0) << level;
}

which makes

const locVal  = foo(loc > 0, 0);
const catVal  = foo(cat > 0, 1);
const priceVal= foo(price > 0, 2)

(我省略了其他变量...)然后将二进制值相加

const total = locVal + catVal + priceVal

那么现在你需要使用一个类似switch case语句的东西。
switch (total) {
    case 0: // all options negative
    case 1: // only loc is positive
    case 2: // only cat is positive
    case 3: // both loc and cat is positive
    ect
}

case中的值代表total中存在的二进制序列的整数值。必须注意,非常重要的是要非常好地记录代码,特别是case块,以便其他读者可以直接弄清楚哪个值代表什么(就像我做的那样)。

如果每个变量有两个以上的选项,则可以按10的因数工作(例如,在foo方法中使用(trueCond ? 1:0) * Math.pow(10,level)


3
这不是一个Java问题。 - user694733

0

由于您的三个条件是固定的,您可以先把它们列出来,然后再处理其他情况,这些情况可以转换为 switch-case 语句。

if(price > 0 || jsBed <= bedroom || jsBuilt >= built) {
    var locCheck = (loc > 0) ? 1 : 0;
    var catCheck = (cat > 0) ? 1 : 0;
    switch(locCheck + catCheck){
        case 0:
            break;
        case 1:
            break;
        case 2:
            break;
        default:
            break;
    }
}

(loc > 0) ? 1 : 0 可以替换为 +(loc > 0)。由于 OP 具有多个 OR 条件,即使最后三个条件为 false,代码也必须执行。你的代码将无法工作。 - Rajesh
这与OP的代码不等价。当“loc”和“cat”为正数时,如果“price> 0 || jsBed <= bedroom || jsBuilt >= built”为false,则代码根本不会执行。而在OP的代码中,第一个“if”语句体将被执行。 - Tushar
嗯,@Tushar 你说得对。调整它会导致与 Mureinik 相似的结果。 - Milan Chheda
案例1需要在其中添加一个附加条件来确定“loc”或“cat”是否为“>0”。或者,您可以使用不同的值来进行“locCheck”和“catCheck”的检查。例如,1和2会给出0、1、2和3作为情况。 - Shaggy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接