【问题标题】:Alternative for multiple if statements多个 if 语句的替代方案
【发布时间】:2012-10-10 15:43:02
【问题描述】:

我的代码包含很多多个if 语句。有没有其他方法可以摆脱这些陈述。例如假设我有以下条件

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

有什么方法可以简化这些语句?

【问题讨论】:

  • 可以分组一些,比如t3 == 0
  • @Ken 在我看来不像一个简单的开关盒。
  • @Ken 他应该如何在不是表达式的条件下切换案例?这不是具有模式匹配的功能语言:)
  • 那是什么语言?为什么你把C放在标签里?我不明白整个问题。
  • @Alonso 对于 t1、t2 和 t3 值可以安全假设什么?我们可以假设它们将是整数吗?

标签: javascript jquery if-statement conditional-statements


【解决方案1】:

您可以使用带有以下条件的 switch case 结构:

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】:

这应该可行:

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

它依赖于 tX 的“真/假”值(0 为假,1-3 为真,有关“真/假”的更多详细信息,请参阅http://11heavens.com/falsy-and-truthy-in-javascript)。

对这种方法的唯一警告是,如果 t1t2t3 均非零,则它允许 selector'div.b_class.c_class.d_class'

如果selector 在这种情况下不可接受,请将t3 条件更改为if (t3 && !(t1 || t2))

t3 条件修改为if (t3 && !(t1 || t2)) 时,selector 可以附加d_class 的唯一方法是t3 不为零并且t1t2 都为零。

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

更新:

最初的答案是我怀疑 OP 的实际意图(因为 OP 暗示代码是假设的),因此感谢 Juve 发现这一点。为了满足cbayram,这将复制 OP 的逻辑(尽管我不确定您是否可以将其称为“简化”,因为它只删除了一个 if 比较并且更难阅读)。

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

下面是它的实际操作:http://jsfiddle.net/dX7AK/

【讨论】:

  • 正确的想法,但执行不力。这与原始条件逻辑的逻辑完全不同。 | div.d_class t1=0,t2=0,t3=2:失败 | div.c_class t1=0, t2=1, t3=1: 失败 | div.c_class t1=0, t2=1, t3=2: 失败 | div.c_class t1=0,t2=2,t3=1:失败 | div.c_class t1=0,t2=2,t3=2:失败 div.b_class.d_class | div.b_class t1=1, t2=0, t3=1: 失败 div.b_class.d_class | div.b_class t1=1, t2=0, t3=2: 失败 | div.b_class.c_class t1=1, t2=1, t3=1: 失败
  • 续... | div.b_class.c_class t1=1,t2=1,t3=2:失败 | div.b_class.c_class t1=1, t2=2, t3=1: 失败 | div.b_class.c_class t1=1,t2=2,t3=2:失败 div.b_class.d_class | div.b_class t1=2, t2=0, t3=1: 失败 div.b_class.d_class | div.b_class t1=2, t2=0, t3=2: 失败 | div.b_class.c_class t1=2,t2=1,t3=1:失败 | div.b_class.c_class t1=2,t2=1,t3=2:失败 | div.b_class.c_class t1=2,t2=2,t3=1:失败 | div.b_class.c_class t1=2,t2=2,t3=2:失败
  • if(t1 == 0 && t2 == 0 && t3 == 1) $('div.d_class').fadeIn();
  • 没错!这种“简单化”的解决方案并没有像 Alonso 所描述的那样。但也许是阿隆索的意图;-)。
【解决方案3】:

好的,假设您确实有很多 ifs 并且您的 ts 是固定整数, 主要目标是您的许多许多“规则”的可读性。那你可以试试下面的方法。

首先我会确保所有ts 都有一个有效值并跳过未定义的情况。 如果变量t 是真实的逻辑值而不是数字,我也只会使用 明确的规则(例如,t1 == 0 而不是使用>, <, >=, <=),尤其是。如果您要实施的规则与您在if 语句中表达的规则一样多样化。

然后您可以使用数字系统对逻辑进行编码,例如,使用小数以获得良好的可读性。 对于每个t,您使用新“逻辑数”的一个小数位来编码您的逻辑:

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

该号码很容易从您的t1t2t3 创建:

num = t1*100 + t2*10 + t3

下面的 switch-case 实现了您的逻辑。它是您的 if 规则的展开版本。 通过不允许多值检查(通过>= 等),我们需要为每个 您要处理的组合。这可能会增加您必须指定的数量或规则 但也可能使您的逻辑规则更具可读性和可维护性。

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 ""

}

您还可以使用数学或其他类型的测试来推理数字。

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"

但我更喜欢 switch-case,因为它读起来更好看。 我希望这是您想要实现的目标。 :)

您可以在this fiddle 中查看此十进制逻辑的运行版本。

干杯, 尤文

【讨论】:

  • switch 声明很痛。
  • 我知道,但他写道,他有“很多”if 声明。我假设他有一些更复杂的逻辑(因为他的ts 可以取四个不同的值)。对于一个真正的四值逻辑,你不能轻易地拥有一个非常短且很好读的解决方案。您需要处理所有不同的可能性。
  • 不过,在这种情况下你可以使用fall-through。
  • 嗯,好的。我没有想到。感谢您的提示!
  • 感谢尤文。你的回答值得一票。从你的回答中得到一个想法。
【解决方案4】:

如果 t1、t2、t3 为 0 到正无穷大,修改后的逻辑有点浓缩:

<!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>

无论哪种情况,这是测试您的修改与原始版本的好方法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 1970-01-01
    • 2014-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多