最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to eliminate if-else when doing different things according to different combinations of boolean value? - Stack

programmeradmin2浏览0评论

for example, suppose I need to do different things according to binations of boolean values: cond_0,cond_1 and cond_2 :

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

it looks as if mapping bit numbers to functions:

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

while the general rule looks like very simple, I don't know how to write it without if-else, and the current form looks like that:

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

which is very long and hard to read. And when a new boolean condition cond_3 is added, it is horrible to modify the code:

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

Is there any way to eliminate the if else, so that cond_0 , cond_1 and cond_2 can just appear once only inside the function, and also easy to add new function when cond_3 is added? I want something like:

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

for example, suppose I need to do different things according to binations of boolean values: cond_0,cond_1 and cond_2 :

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

it looks as if mapping bit numbers to functions:

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

while the general rule looks like very simple, I don't know how to write it without if-else, and the current form looks like that:

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

which is very long and hard to read. And when a new boolean condition cond_3 is added, it is horrible to modify the code:

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

Is there any way to eliminate the if else, so that cond_0 , cond_1 and cond_2 can just appear once only inside the function, and also easy to add new function when cond_3 is added? I want something like:

var f=function(cond_0,cond_1,cond_2){
  var magic=(000:a,001:b,010:c...);
  magic(cond_0,cond_1,cond_2)();
}
Share Improve this question edited Feb 15, 2018 at 3:34 ofd asked Feb 15, 2018 at 3:28 ofdofd 4,0202 gold badges13 silver badges23 bronze badges
Add a ment  | 

6 Answers 6

Reset to default 4

See this implementation. Here all the three parameters (boolean expected) are multiplied by their place values to form the number and then padded with '0' to the desired length. This value is searched for in the magic object and the function if defined is called.

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

Because true to number is 1, true * 2 is 2, etc.. probably something like this:

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

Use a bit of bitwise operations and binary literals as object keys:

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

This object is essentially the same as the array literal in @Slai's answer, just with explicit indices.

It gets much crazier if you directly declare your functions as methods of the object instead of naming them individually:

const magic = {
  0b000() { console.log("a"); … },
  0b001() { console.log("b"); … },
  0b010() { console.log("c"); … },
  0b011() { console.log("d"); … },
  0b100() { console.log("e"); … },
  0b101() { console.log("f"); … },
  0b110() { console.log("g"); … },
  0b111() { console.log("h"); … },
};

You had the right idea at the top. You can encode the functions in a map just like you put together conceptually by implicitly casting booleans to integers. Below is an implementation which can be easily extended to handle more states/functions.

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



  • I need to do different things according to binations of boolean values
  • and also easy to add new function when cond_3 is added

There is no need to name them, just iterate over the set of arguments in the function.

//range of preset functions styled as OP described
function a(){ console.log('a'); }
function b(){ console.log('b'); }
function c(){ console.log('c'); }
function d(){ console.log('d'); }
function e(){ console.log('e'); }
function f(){ console.log('f'); }
function g(){ console.log('g'); }
function h(){ console.log('h'); }
function i(){ console.log('i'); }
function j(){ console.log('j'); }
function k(){ console.log('k'); }
function l(){ console.log('l'); }
function m(){ console.log('m'); }

//This function will take the arguments, reduce their boolean value 
//to a 1 or 0 using |0, concatenate the string of 1's and 0's,
//parse out the string from binary to decimal, and then
//access the array's index correlating to the given decimal.
var truthTable = function(){
    var callers = [a,b,c,d,e,f,g,h,i,j,k,l,m];
    var tar = [].reduce.call(arguments,(p,c) => p+(c|0),"");
    callers[parseInt(tar,2)]();
};
truthTable (true,true,false);
truthTable (true,false,true);
truthTable (true,true);
truthTable (true,true,false,false);

As written, this will scale as far as it needs to provided that the decimal index of each function in callers correlates to its truth table value.

Look at switches on mdn: switch https://developer.mozilla/en-US/docs/Web/JavaScript/Reference/Statements/switch

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论