多重if语句的替代方案

4
我的代码包含很多重复的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();

有没有简化这些语句的方法?

3
你可以将一些东西分组,比如 t3 == 0 - chris
@Ken 看起来不像是简单的 switch case。 - DrummerB
@Ken:正如我所说,这不是一种具有模式匹配功能的函数式语言。 - Jack
3
那是什么语言?为什么你在标签中加入了 C ?我不理解整个问题。 - Ken
2
@Alonso,对于t1、t2和t3的值,我们可以假设它们是整数吗? - cbayram
显示剩余13条评论
4个回答

5
你可以使用带有条件的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;
}

1
这不仅仅是简单地重写代码。他在寻求一种“简化”的方法。 - Juve

1

好的,假设您确实有很多if语句,而且您的t是固定整数, 并且主要目标是使您的许多“规则”易于阅读。那么您可以尝试以下方法。

首先,我会确保所有的t都有有效值,并跳过未定义的情况。 如果变量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,因为它读起来更加流畅。

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


那个switch语句太糟糕了。 - Bergi
我知道,但他写道他有“很多”if语句。我猜他有一些更复杂的逻辑(因为他的t可以取四个不同的值)。对于真正的四值逻辑,你不能轻易地得到一个非常简短和易读的解决方案。你需要处理所有不同的可能性。 - Juve
不过,在这种情况下,你本可以使用“fall-through”。 - Bergi
嗯,好的。我没有想到。谢谢你的提示! - Juve
谢谢Juve。你的回答值得点赞。从你的回答中得到了一个想法。 - Alonso

1

这应该可以工作:

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))时,只有当t3为非零且t1t2都为零时,selector才能附加d_class

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

这是一个IT相关的内容:“这里有一个它正在运行的小玩意儿:http://jsfiddle.net/dX7AK/”。

1
正确的想法,但执行很差。这根本不是原始条件逻辑的相同逻辑。| 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:失败 - cbayram
继续... | 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:失败 - cbayram
如果(t1 == 0 && t2 == 0 && t3 == 1) $('div.d_class').fadeIn(); - cbayram
1
没错!这个“简化”方案并没有做到阿隆索描述的那样。但也许符合阿隆索的本意吧 ;-). - Juve

0
如果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>

无论哪种情况,这都是测试您的修改与原始代码之间差异的好方法。

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