19

I am trying to write a switch statement but it doesn't seem to work how I want.

getExerciseDescription(exerciseId, intensity_level){

    alert(exerciseId + " " + intensity_level)

    switch (exerciseId && intensity_level) {
        case (1 && 1):
        this.header="Exercise 1 Level 1";
        this.instructions="Exercise 1 Level 1";
        break;
        case (1 && 2):
        this.header="Exercise 1 Level 2";
        this.instructions="Exercise 1 Level 2";
        break;  


        case (2 && 1):
        this.header="Exercise 2 Level 1";
        this.instructions="Exercise 2 Level 1";
        break;  
        case (2 && 2):
        this.header="Exercise 2 Level 2";
        this.instructions="Exercise 2 Level 2";
        break;

        default:
        this.header="Default";
        this.instructions="Default";
        break;
    }

    return new Popup(this.header, this.instructions);
} 

The alerts gives 2 and 1 but the returned value is for (1 && 1). Why is it so? How can I fix this?

Charles Clayton
  • 17,005
  • 11
  • 87
  • 120
Thinker
  • 5,326
  • 13
  • 61
  • 137

4 Answers4

24

You just can't use a switch like that. (1 && 1) == (2 && 1) == 1 and (1 && 2) == (2 && 2) == 2, so you're doing the equivalent of:

    switch (exerciseId && intensity_level) {
        case (1): //...
        case (2): //...

        case (1): // same as above
        case (2): // same as above

        default:
        //...
   }

So of course the lower two cases will never execute. You're better of just using if and else if statements, or maybe nested switches if you want.

You could also do something like:

switch (exerciseId + " " + intensity_level) {
    case("1 1"): ...
    case("1 2"): ...
    case("2 1"): ...
    case("2 2"): ...
Charles Clayton
  • 17,005
  • 11
  • 87
  • 120
  • 1
    Just be warned, you take a performance hit comparing strings instead of numbers. Although with a string length of 3, it's probably not going to make any noticeable impact - see http://stackoverflow.com/a/23837610/6806381 – Christopher Moore Mar 05 '17 at 18:52
3

That isn't how a switch statement will evaluate. For your scenario it will always evaluate to the 2nd integer in the logical and &&.

(More information about Logical Operators)

Logical AND (&&)

expr1 && expr2

Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.

You actually don't even need to use a switch, you can write it with a simple if

if (exerciseId <= 2 && intensity_level <= 2){
    this.header=`Exercise ${exerciseId} Level ${intensity_level}`;
    this.instructions=`Exercise ${exerciseId} Level ${intensity_level}`;
} else {
    this.header="Default";
    this.instructions="Default";
}
Community
  • 1
  • 1
Christopher Moore
  • 3,071
  • 4
  • 30
  • 46
  • `"Exercise 1 Level 1"` for header and content was just an example, actually for each case there are different textual headers and instructions. So if else would be difficult. – Thinker Mar 05 '17 at 18:37
  • Ok - you will most likely need to resort to multiple `if` statements then – Christopher Moore Mar 05 '17 at 18:39
  • I tried the above solution with string, it is lengthy but it worked. `this.switchString=exerciseId + " " + intensity_level` and then `switch (this.switchString){case ("1 1"): ..}` – Thinker Mar 05 '17 at 18:40
  • String comparison is significantly slower than with numbers. I would advise against using strings just so you can use a `switch` statement – Christopher Moore Mar 05 '17 at 18:44
  • Okay sure. I will modify the code accordingly then. Thanks! – Thinker Mar 05 '17 at 18:47
2

You can use switch(true) then now you can use logical operator on case.

switch (true) 
{
        case (1 && 1):
        this.header="Exercise 1 Level 1";
        this.instructions="Exercise 1 Level 1";
        break;
        case (1 && 2):
        this.header="Exercise 1 Level 2";
        this.instructions="Exercise 1 Level 2";
        break;  

        case (2 && 1):
        this.header="Exercise 2 Level 1";
        this.instructions="Exercise 2 Level 1";
        break;  
        case (2 && 2):
        this.header="Exercise 2 Level 2";
        this.instructions="Exercise 2 Level 2";
        break;

        default:
        this.header="Default";
        this.instructions="Default";
        break;
    }
0

The logical operators &&, || and ! always return true or false so the possible switch cases are only true and false. You should go with strings or numbers cases only.

Babar Hussain
  • 2,917
  • 1
  • 17
  • 14