Can I use a case/switch statement with two variables?
Asked Answered
F

11

69

I am a newbie when it comes to JavaScript and it was my understanding that using one SWITCH/CASE statements is faster than a whole bunch of IF statements.

However, I want to use a SWITCH/CASE statement with two variables.

My web app has two sliders, each of which have five states. I want the behavior to be based on the states of these two variables. Obviously that is a whole heck of a lot of IF/THEN statements.

One way I thought about doing it was concatenating the two variables into one and then I could SWITCH/CASE that.

Is there a better way of accomplishing a SWITCH/CASE using two variables ?

Thanks !

Forage answered 10/2, 2012 at 21:36 Comment(5)
What's in those variables? numbers? strings?Holbert
25 case expressions?! That method will be huge. :-o Are you sure you need separate logic for all 25 states?Manikin
If you have a lot of options, than simply concatenating them to something like var1|var2 may be a very fast way. We'll need to see some examples of what you're doing though...Plainsman
There is probably a much better way to solve your problem. If you give us more info on the actual problem, you will probably get a lot of great suggestions :)Zantos
Actually it is kinda complicated. What I am doing is using the ArcGIS Javascript API and I am displaying different maps based on where the sliders are stationed. What I really wanted to do is use the sliders to do some calculations and then display a map based on those calculations but that did not work out so hot.Forage
C
59

Yes you can also do:

    switch (true) {

     case (var1 === true && var2 === true) :
       //do something
       break;
     case (var1 === false && var2 === false) :
       //do something
       break;

      default:

    }

This will always execute the switch, pretty much just like if/else but looks cleaner. Just continue checking your variables in the case expressions.

Croatia answered 31/8, 2018 at 9:5 Comment(2)
good, but typescript doesnt accept this solutionMasha
@AlexeyNikonov it does for me.Tool
M
35

How about a bitwise operator? Instead of strings, you're dealing with "enums", which looks more "elegant."

// Declare slider's state "enum"
var SliderOne = {
    A: 1,
    B: 2,
    C: 4,
    D: 8,
    E: 16
};

var SliderTwo = {
    A: 32,
    B: 64,
    C: 128,
    D: 256,
    E: 512
};

// Set state
var s1 = SliderOne.A,
    s2 = SliderTwo.B;

// Switch state
switch (s1 | s2) {
    case SliderOne.A | SliderTwo.A :
    case SliderOne.A | SliderTwo.C :
        // Logic when State #1 is A, and State #2 is either A or C
        break;
    case SliderOne.B | SliderTwo.C :
        // Logic when State #1 is B, and State #2 is C
        break;
    case SliderOne.E | SliderTwo.E :
    default:
        // Logic when State #1 is E, and State #2 is E or
        // none of above match
        break;


}

I however agree with others, 25 cases in a switch-case logic is not too pretty, and if-else might, in some cases, "look" better. Anyway.

Myrtismyrtle answered 10/2, 2012 at 21:50 Comment(4)
single | or double || ?Dispensation
Single. We're talking 'bitwise or' here. Reference: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…Spalding
When the enums are not defined in a bit range this does not work, so it's a misleading instruction.Christianize
This might be efficient, but wouldn't help readability. Not every dev understands bitwise.Immunoreaction
P
26
var var1 = "something";
var var2 = "something_else";
switch(var1 + "|" + var2) {
    case "something|something_else":
        ...
        break;
    case "something|...":
        break;
    case "...|...":
        break;
}

If you have 5 possibilities for each one you will get 25 cases.

Paronomasia answered 10/2, 2012 at 21:39 Comment(7)
This, along with every other answer here, is horrible. The correct answer is to use if...Substance
consider the case var1 = "something|something_else"; and var2 = "";Raymund
@BrianHannay an extra | is inserted, the case would have to be "something|something_else|". While it's not brilliant, my answer assumes you have complete control over var1 and var2. If you assume you don't, what would your answer be?Paronomasia
@Paronomasia I don't believe there is a very good way to do it, but nested switch statements (with variable options) could work. I just can't think of a case where the resulting action from the second slider (in OP's question) would depend on the value of the first.Raymund
@BlueRaja-DannyPflughoeft so true :)Rejoinder
encodeURIComponent(left) + "#" + encodeURIComponent(right) (lord help me)Cythiacyto
this is a footgunDuhon
L
15

First, JavaScript's switch is no faster than if/else (and sometimes much slower).

Second, the only way to use switch with multiple variables is to combine them into one primitive (string, number, etc) value:

var stateA = "foo";
var stateB = "bar";
switch (stateA + "-" + stateB) {
    case "foo-bar": ...
    ...
}

But, personally, I would rather see a set of if/else statements.

Edit: When all the values are integers, it appears that switch can out-perform if/else in Chrome. See the comments.

Lampedusa answered 10/2, 2012 at 21:40 Comment(6)
Repeat the same test, but with. say, 100 cases. The differences will become noticeable.Single
Ah, on my browser, you seem to be correct when the value being switched over is an integer: jsperf.com/switch-ifelse-map/3Lampedusa
doesn't necessarily have to be an integer. Your test case has to be modified though. Hashes are often the most efficient option out of switch, else if and {}. The overhead of creating a hash becomes negligible when checking often. It outperforms switch and else if in the long run.Single
Oh, nuts, but it seems like my number test case was overwritten by my string test case. Anyway, numbers are faster, strings are identical.Lampedusa
Hi David, Thanks that is pretty awesome to be able to compare switching vs if/else and do it by integers and strings. Seems like switch and integer is fastest for FF9.01Forage
Test links are now broken.Earreach
L
6

I don't believe a switch/case is any faster than a series of if/elseif's. They do the same thing, but if/elseif's you can check multiple variables. You cannot use a switch/case on more than one value.

Leanto answered 10/2, 2012 at 21:39 Comment(0)
C
5

If the action of each combination is static, you could build a two-dimensional array:

var data = [
  [1,2,3,4,5],
  [6,7,8,9,10],
  [11,12,13,14,15],
  [16,17,18,19,20],
  [21,22,23,24,25]
];

The numbers in above example can be anything, such as string, array, etc. Fetching the value is now a one-liner (assuming sliders have a value range of [0,5):

var info = data[firstSliderValue][secondSliderValue];
Crawly answered 5/2, 2015 at 5:9 Comment(0)
I
4

You could give each position on each slider a different binary value from 1 to 1000000000 and then work with the sum.

Immortalize answered 10/2, 2012 at 21:47 Comment(0)
T
4

Yeah, But not in a normal way. You will have to use switch as closure.

ex:-

function test(input1, input2) {
     switch (true) {
        case input1 > input2:
                    console.log(input1 + " is larger than " + input2);
                    break;
        case input1 < input2:
                    console.log(input2 + " is larger than " + input1);
        default:
                    console.log(input1 + " is equal to " + input2);
      }
   }
Twentyfour answered 15/6, 2018 at 9:29 Comment(0)
L
4

I did it like this:

switch (valueA && valueB) {

case true && false:
console.log(‘valueA is true, valueB is false’)
break;

case ( true || false ) && true:
console.log(‘valueA is either true or false and valueB is true’)
break;

default:
void 0;
}
Loon answered 13/9, 2021 at 15:21 Comment(0)
M
0

In the same vein as above-mentioned concatenation methods but more tastefully - and likely efficiently ? - for numbers you could use a simple bijection (specifically I used this with couples of positive integers, and I wouldn't have any confidence about floating point / real numbers bijections)

If you are only dealing with numbers, you could use simple bijections

For example : Cantor pairing function from N² to N

function c(a, b) {
  if (b === 0){
    return a * (a + 1) / 2;
  } else {
    return b + c(a + b, 0);
}

Then

function(a, b) {
  switch(c(a, b)) {
    case c(0, 0):
    // ...
    case c(1, 0):
    // ...
    case c(0, 1):
    // ...
    case c(1, 1):
    // ...
    case c(2, 1):
    // ...
  }
}

The same should be safely feasible for tuples of integers of any length n since Z^n has the same cardinality as N.

Methylal answered 24/4 at 21:19 Comment(0)
L
0

Here's the approach I would take, which I think is cleaner than the other proposals:

const doState = {
1: {
   1: func_1_1,
   2: func_1_2,
   3: function() { return false; }
   4: x => x-1,
   5: ...
   },
2: { ... }
...
}

const logic = doState[slider1] && doState[slider1][slider2]
if(!logic) return console.error("Unsupported program state")
return logic()

This lets you keep all your program logic well organized into discrete functions that can be reused and instead of dealing with conditionals doing the right thing is a simple dictionary lookup. The statement with the && is just checking to ensure the first item is defined to avoid an error on undefined, and the return value is the result of the logic but you could return the function directly depending on what makes sense in your application.

Logue answered 26/4 at 4:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.