如何在根据布尔值的不同组合做不同的事情时消除if-else?

时间:2018-02-15 03:28:04

标签: javascript if-statement

例如,假设我需要根据布尔值的组合做不同的事情:cond_0,cond_1和cond_2:

cond_0 cond_1 cond_2
false  false  false  a();
false  false  true   b();
.
.
.
true   true   true   h();

看起来好像将位数映射到函数:

000:a()
001:b()
.
.
.
111:h()

虽然一般规则看起来很简单,但我不知道如何在没有if-else的情况下编写它,并且当前表单看起来像这样:

var f=function(cond_0,cond_1,cond_2){
  if(!cond_0 && !cond_1 && !cond_2){
    a();
  }else if( cond_0 && !cond_1 && !cond_2)){
    b();
  }else if(!cond_0 &&  cond_1 && !cond_2)){
    c();
  }else if( cond_0 &&  cond_1 && !cond_2)){
    d();
  }else if(!cond_0 && !cond_1 &&  cond_2)){
    e();
  }else if( cond_0 && !cond_1 &&  cond_2)){
    f();
  }else if(!cond_0 &&  cond_1 &&  cond_2)){
  g();
  }else if( cond_0 &&  cond_1 &&  cond_2)){
    h();
  }
}

很长很难读。当添加新的布尔条件cond_3时,修改代码是非常糟糕的:

if(!cond_0 && !cond_1 && !cond_2 && !cond_3){
    a();
  }else if( cond_0 && !cond_1 && !cond_2 !cond_3)){
    b();
  }
  .
  .
  .

有没有办法消除if else,这样cond_0,cond_1和cond_2只能在函数内部出现一次,并且在添加cond_3时也很容易添加新函数?我想要这样的东西:

var f=function(cond_0,cond_1,cond_2){
  var magic=(000:a,001:b,010:c...);
  magic(cond_0,cond_1,cond_2)();
}

6 个答案:

答案 0 :(得分:4)

请参阅此实施。这里所有三个参数(预期的布尔值)乘以它们的位置值以形成数字,然后用'0'填充到所需的长度。在magic对象中搜索此值,并调用定义的函数。

var a = function() {
  console.log('a() called');
};
var b = function() {
  console.log('b() called');
};
var c = function() {
  console.log('c() called');
};

var f = function(cond_0, cond_1, cond_2) {
  var cond = ((cond_0 * 100) + (cond_1 * 10) + (cond_2)).toString().padStart(3, '0');
  var magic = {
    '000': a,
    '001': b,
    '010': c
  };
  if (typeof magic[cond] === 'function') {
    magic[cond]();
  } else {
    console.log('No function defined for this cond');
  }
}

f(false, false, false);
f(false, false, true);
f(false, true, false);
f(true, false, false);

答案 1 :(得分:2)

因为数字true为1,true * 2为2,等等。可能是这样的:

function f(c0, c1, c2) { [a, b, c, d, e, f, g, h][+c0 +c1 * 2 +c2 * 4](); }    // magic

答案 2 :(得分:1)

使用一些按位运算和二进制文字作为对象键:

using (MySqlCommand cmd = new MySqlCommand(commandLine, connect))
{
    connect.Open();
    return Convert.ToInt32(cmd.ExecuteScalar());
}

这个对象与@Slai的答案中的数组文字基本相同,只是显式索引。

如果你直接将你的函数声明为对象的方法而不是单独命名它们会变得更加疯狂:

function f(cond_0, cond_1, cond_2) {
  const magic = {
    0b000: a,
    0b001: b,
    0b010: c,
    0b011: d,
    0b100: e
    0b101: f,
    0b110: g,
    0b111: h,
  };
  return magic[cond_2 << 2 | cond_1 << 1 | cond_0 << 0]();
}

答案 3 :(得分:0)

你在顶部有正确的想法。您可以在地图中对函数进行编码,就像通过隐式地将布尔值转换为整数一样在概念上进行编码。下面是一个可以轻松扩展以实现更多状态/功能的实现。

//initialization
var bitmap = {};
bitmap[0] = a;
bitmap[1] = b;
bitmap[10] = c;
bitmap[11] = d;
bitmap [110] = e;

var inputBools = [true, true, false];

pickFunction(inputBools);


function pickFunction(bools){
  var key = 0;
  for (var i = 0; i < bools.length; i++){
    key += bools[bools.length-1-i]*Math.pow(10,i);
  }
  console.log(bitmap[key].call());
}

function a(){
  return "a";
}

function b(){
  return "b";
}

function c(){
  return "c";
}


function d(){
  return "d";
}

function e (){
   return "e";
 }

答案 4 :(得分:0)

  
      
  • 我需要根据布尔值
  • 的组合做不同的事情   
  • 并且在添加cond_3时也很容易添加新功能
  •   

无需为它们命名,只需迭代函数中的参数集。

&#13;
&#13;
  kapt "com.google.dagger:dagger-compiler:$rootProject.daggerVersion"
&#13;
&#13;
&#13;

如上所述,只要需要调用者中每个函数的十进制索引与其真值表值相关,这将进行扩展。

答案 5 :(得分:-1)