176

I want to do something like this

    switch (this.dealer) {
        case 1-4: 
            // Do something.
            break;
        case 5-8: 
            // Do something.
            break;
        case 9-11: 
            // Do something.
            break;
        default:
            break;
    }

What is the right syntax for this? Is it possible in JavaScript?

So this.dealer is an integer, and if it's between those values, do something.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Jaanus
  • 16,161
  • 49
  • 147
  • 202
  • This feature (range values in switch) was available and used regularly in B with no ill effects. Unfortunate that it never managed to get adopted into the descendants of K&R C (which syntactically includes Javascript). #OldManRant – Ron Burk Dec 23 '19 at 00:50

8 Answers8

392

Here is another way I figured it out:

const x = this.dealer;
switch (true) {
    case (x < 5):
        alert("less than five");
        break;
    case (x < 9):
        alert("between 5 and 8");
        break;
    case (x < 12):
        alert("between 9 and 11");
        break;
    default:
        alert("none");
}
mruanova
  • 6,351
  • 6
  • 37
  • 55
Alejandro Martin
  • 5,691
  • 1
  • 17
  • 21
  • 30
    Sure, a neat trick, but at that point what's the benefit over just a chain of if else if statements? – xtempore May 31 '13 at 00:15
  • 23
    This could be improved significantly by removing each of the > comparisons, they just make it confusing. By the second case we know that x must not be less than 5, so we might as well not include the overlapping comparisons - they'll just cause confusion later on. – David Mason Oct 09 '13 at 23:34
  • 1
    @xtempore : Then you can eliminate switchs from all languages, as switch functionliaty can always be replaced with if statements. – Alejandro Martin Jul 20 '14 at 19:45
  • @DavidMason: I think the example is easier to understand as it is now. I was not writing here production code, nor trying to optimize. – Alejandro Martin Jul 20 '14 at 19:51
  • 9
    @Alejandro Martin : Switch statements are useful because they provide code that is more concise and more readable. Your example requires more lines than are necessary, and the code is far less clear than the equivalent if-then-else structure. It's simply a case of the right structure for the job. Just because you were able to create obscure sub-optimal code using a switch statement does not provide a rationale to remove switch statements from all languages. – xtempore Jul 21 '14 at 08:03
  • 2
    @xtempore : Maybe its far less clear to you, and maybe for the person who asked the question a chain of if else statements is harder to read. It's subjective. To me it really doesn't matter at all, I never needed to use a switch in javascript in this way. But other people maybe found useful this kind of technique. Anyway, I think you are missing the point of the question. Somebody asked if it was possible a switch with int ranges in javascript and the answer shows that it is possible. Period. – Alejandro Martin Jul 21 '14 at 10:27
  • 1
    @Alejandro Martin: He gave a switch statement in his example, but never specifically said he wanted to use one. Using a switch statement is a poor choice, and that should have been pointed out, rather than just doing some "trick" to use a switch where if-then-else is far cleaner. My initial question was to ask what benefit there would be to a switch. You never responded to that. Instead you became reactionary declaring that we might as well remove switch from all languages. – xtempore Jul 21 '14 at 23:36
  • @AlejandroMartin I have to disagree. Having a line that says `case (x > 4 && x < 9):` could very easily mislead someone into thinking that the line would be run for numbers ranging from roughly `4.00000001` to `8.999999999`, which is just wrong. The `x > 4 &&` adds confusion, and does not make the code any safer or more correct. Such code should not be kept. – David Mason Aug 09 '14 at 23:37
  • @AlejandroMartin I am not sure why you mention production code and optimization - some optimizations for speed or space can make code harder to read, but aside from that there is never any reason to write confusing code, regardless whether it is "production" code. – David Mason Aug 09 '14 at 23:40
  • @DavidMason The code its "confusing" just because you say it. I think it is clearer the way I wrote it, as illustrates the answer in the same way the question was made – Alejandro Martin Aug 11 '14 at 10:00
  • @xtempore I did not answer to that because your question have nothing to do with the problem exposed here. If you want discuss whether switches are always useful or not in javascript, you can open a new question for that. – Alejandro Martin Aug 11 '14 at 10:11
  • @AlejandroMartin it is not confusing just because I say it is - I have explained specifically what I consider confusing about it in the comment beginning with "@AlejandroMartin I have to disagree. Having a line that says...". You are welcome to disagree with that point, but I certainly have not stated that anything is "just because [I] say it" - that is a straw man argument, and so has no place in reasonable discussion. – David Mason Aug 15 '14 at 01:18
  • 4
    @xtempore I benefited from this answer and used in my ugly code just to get things working. Yes I do agree I want something more optimized and neat which works well with the piece of software I'm writing. But the truth is this that guys like me came here to get there things fixed and remember every beginner reached at top if they keep rolling and do not stop at the point whether it is better or worse. It really matters that he/she getting things done. They learn in a while it takes time. – Superman Jan 09 '15 at 04:10
  • 2
    I personally felt there are more down voters on SO then the ppl who really want to resolve others problems and willing to answer them in order to help them out. I'm here to appreciate them. And not here to criticize the other group of ppl. Because they had to learn the thing that what is NEED? Once they will they will be fine. :) – Superman Jan 09 '15 at 04:12
  • 1
    @Superman I absolutely agree that just getting the job done is sometimes important, but why not LEARN SOMETHING along the way. After all isn't that why we're here? I've added an ANSWER below using if...else... For me the code is clearer (my opinion), more concise (fact), and faster (fact). – xtempore Jan 10 '15 at 01:26
  • @AlejandroMartin While I was running a test (jsFiddle) I noticed an error in your code. I does not correctly handle the case where this.dealer = 0 (the OP wanted 1-4, but you use < 5) – xtempore Jan 10 '15 at 01:27
  • 2
    @xtempore You both are absolutely right and you both are knowledgeable the point is just that right now that you both bit dislike each other due to this conversation. I would advise that you both give each other smile and do not fire up the talk. Alejandro just tried to help the person. And you just trying to tell something to learn. This shows that you both are awesome and you both are gems of the community. Please forgive each other stay calm and smile at each other. We the community's junior and less knowledgeable people salute you both. :) – Superman Jan 10 '15 at 05:46
  • 5
    @Superman you make an excellent point. I think it is important for everyone to remember that the code is what we are talking about, not the people. If someone points out a problem with some code I write, I learn something and write better code next time. I can't afford to take it personally: I am not the code, and the code is not me or my baby. If I try to defend all my code from any criticism, I will never fix all my bad habits or learn anything new. – David Mason Mar 26 '15 at 02:14
  • 1
    For me, the code is much more readable using `switch` than `if-else`. I like this answer and will use it when I need range in conditional. – 5413668060 Jun 27 '19 at 03:34
  • While I think this code is a little obscure, it may benefit people to understand what is going on here. A switch/case statement works by matching the part in the switch with each case, and then executing the code on the first match. In most use cases, we have a variable or non-constant expression in the switch, and then match it. Here, because the switch is on true, we will find the first expression in the case statements that is true. If you read "switch (true)" as "find the first expression that is true" then the code certainly feels more readable. – xtempore Jan 27 '20 at 23:19
  • personally, i find switch statements more readable than if...else statements, generally speaking. – johny why May 04 '20 at 18:22
  • Very creative!! Would not do it like this though. I'd prefer using if's over this. – Elmer Dec 21 '20 at 15:20
56

Incrementing on the answer by MarvinLabs to make it cleaner:

var x = this.dealer;
switch (true) {
    case (x < 5):
        alert("less than five");
        break;
    case (x < 9):
        alert("between 5 and 8");
        break;
    case (x < 12):
        alert("between 9 and 11");
        break;
    default:
        alert("none");
        break;
}

It is not necessary to check the lower end of the range because the break statements will cause execution to skip remaining cases, so by the time execution gets to checking e.g. (x < 9) we know the value must be 5 or greater.

Of course the output is only correct if the cases stay in the original order, and we assume integer values (as stated in the question) - technically the ranges are between 5 and 8.999999999999 or so since all numbers in js are actually double-precision floating point numbers.

If you want to be able to move the cases around, or find it more readable to have the full range visible in each case statement, just add a less-than-or-equal check for the lower range of each case:

var x = this.dealer;
switch (true) {
    case (x < 5):
        alert("less than five");
        break;
    case (x >= 5 && x < 9):
        alert("between 5 and 8");
        break;
    case (x >= 9 && x < 12):
        alert("between 9 and 11");
        break;
    default:
        alert("none");
        break;
}

Keep in mind that this adds an extra point of human error - someone may try to update a range, but forget to change it in both places, leaving an overlap or gap that is not covered. e.g. here the case of 8 will now not match anything when I just edit the case that used to match 8.

    case (x >= 5 && x < 8):
        alert("between 5 and 7");
        break;
    case (x >= 9 && x < 12):
        alert("between 9 and 11");
        break;
David Mason
  • 2,917
  • 4
  • 30
  • 45
  • 3
    Imho this is very bad style - the correctness of the switch statement now depends on the order of the cases. This harms readability and maintainability, in particular for case statements that no longer fit into the current editor viewport (though some argue to avoid lengthy structures like this anyway), and afaik may actually hinder optimizations ( you can no longer order the cases according to decreasing frequency of runtime occurrence). – collapsar Mar 25 '15 at 14:28
  • 3
    @collapsar case statements in JavaScript are fundamentally order-dependent. It would be unwise to ever start blindly reordering the cases. That optimization you are talking about is only relevant in some very limited situations - most programs would never see any benefit from such optimizations, so I don't see any value in writing code to cater to them - it makes the rare case that such an optimization is needed a little more work, but the difference is trivial. – David Mason Mar 26 '15 at 01:51
  • 2
    @collapsar readability concerns are worth consideration though, and if you can consistently use a switch statement such that each case is mutually exclusive (so essentially as though it were a shorter syntax for a set of if-then-else statements) I can see the benefit on cognitive load. The addition then would be to add a `>=` check for the lower range to each case. If you care about premature performance micro-optimizations, keep in mind that this is one extra numeric comparison for the interpreter to deal with. – David Mason Mar 26 '15 at 01:57
29
    switch(this.dealer) {
        case 1:
        case 2:
        case 3:
        case 4:
            // Do something.
            break;
        case 5:
        case 6:
        case 7:
        case 8:
            // Do something.
            break;
        default:
            break;
    }

If you don't like the succession of cases, simply go for if/else if/else statements.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vincent Mimoun-Prat
  • 28,208
  • 16
  • 81
  • 124
  • 10
    This is a better solution imo because it actually demonstrates one of the reasons switch's were invented. – Jake Wilson May 20 '13 at 02:40
  • 1
    This will work for small ranges, in my case where the range is bigger(>=100) this would be a nightmare to type out – Femi Oni Nov 24 '18 at 11:09
19

This does not require a switch statement. It is clearer, more concise, faster, and optimises better, to use if else statements...

var d = this.dealer;
if (1 <= d && d <= 11) { // making sure in range 1..11
    if (d <= 4) {
        alert("1 to 4");
    } else if (d <= 8) {
        alert("5 to 8");
    } else {
        alert("9 to 11");
    }
} else {
    alert("not in range");
}

Speed test

I was curious about the overhead of using a switch instead of the simpler if...else..., so I put together a jsFiddle to examine it... http://jsfiddle.net/17x9w1eL/

  • Chrome: switch was around 70% slower than if else

  • Firefox: switch was around 5% slower than if else

  • IE: switch was around 5% slower than if else

  • Safari: switch was around 95% slower than if else

Notes:

Assigning to the local variable is optional, especially if your code is going to be automatically optimised later.

For numeric ranges, I like to use this kind of construction...

if (1 <= d && d <= 11) {...}

... because to me it reads closer to the way you would express a range in maths (1 <= d <= 11), and when I'm reading the code, I can read that as "if d is between 1 and 11".

Clearer

A few people don't think this is clearer. I'd say it is not less clear as the structure is close to identical to the switch option. The main reason it is clearer is that every part of it is readable and makes simple intuitive sense.

My concern, with "switch (true)", is that it can appear to be a meaningless line of code. Many coders, reading that will not know what to make of it.

For my own code, I'm more willing to use obscure structures from time to time, but if anyone else will look at it, I try to use clearer constructs. I think it is better to use the constructs for what they are intended.

Optimisation

In a modern environment, code is often going to be minified for production, so you can write clear concise code, with readable variable names and helpful comments. There's no clear reason to use switch in this way.

I also tried putting both constructs through a minifier. The if/else structure compresses well, becoming a single short expression using nested ternary operators. The switch statement when minified remains a switch, complete with "switch", "case" and "break" tokens, and as a result is considerably longer in code.

How switch(true) works

I think "switch(true) is obscure, but it seems some people just want to use it, so here's an explanation of why it works...

A switch/case statement works by matching the part in the switch with each case, and then executing the code on the first match. In most use cases, we have a variable or non-constant expression in the switch, and then match it.

With "switch(true), we will find the first expression in the case statements that is true. If you read "switch (true)" as "find the first expression that is true", the code feels more readable.

xtempore
  • 5,260
  • 4
  • 36
  • 43
  • 6
    ymmv - in fact, wrt clarity, I feel this code being harder to read than a searched switch statement. The speed tests do not convince me - the statement will be a tiny snippet of the code base. Whether or not it is worth to be optimized, only profiling or careful contextual analysis can tell, and in case it is, you usually gain more by ordering the cases by decreasing frequency of runtime occurrence. (This comment isn't mean to mark your method as inferior; as said before, ymmv, and, of course, all claims imho only ;-) ), – collapsar Mar 25 '15 at 14:43
  • 2
    not more clear imo – FluffyBeing Dec 13 '16 at 18:05
  • @zeion How many coders do you think would immediately understand what "switch (true) {" does? My guess is not too many. Including it is what makes that code unclear. – xtempore Dec 13 '16 at 20:38
  • @collapsar The speed issue was more a curiosity. I thought perhaps there might be some benefit to the switch option, but there wasn't. Speed on that type of code probably isn't important, but the significant difference also tells me that the switch construct wasn't intended to be used in that way. It's a hack. It's unclear, and we already have a construct for that purpose. – xtempore Dec 13 '16 at 20:38
  • Notable that today on Chrome 58.0.3029.110, I got wildly different results on that JSFiddle, with `if` always being slower, anywhere from 2-12% _slower_ than switch on ~10 consecutive runs. – nickcoxdotme Jun 02 '17 at 23:07
  • @nickcoxdotme Just revisiting this so thought I'd recheck. Tried many times and got switch being 8% slower (on Chrome 64.0.3282.71 (Official Build) beta (64-bit)), but like I said, the speeds not the important issue, perhaps more a side-effect of what the compiler expects switch to be used for. – xtempore Jan 12 '18 at 00:21
  • 2
    Just throwing my 2 cents out there ... I tend to find that choosing between a switch statement and cascading if/else statements (excluding the concerns about switch(true)) comes down to two things: 1) How many cases are there? Anything beyond 5 I find switches are easier to read. 2) How likely am I to go back and add additional cases? It's quicker to added another case than it is to add another else if block (or at least it feels that way when trying to get a hotfix out to production) – darkrat May 01 '18 at 17:58
  • 3
    you are not answering the question. op intend to use `switch` – wdetac Jun 27 '19 at 03:40
  • 5
    disagree, It is much more clear to use `switch` – 5413668060 Jun 27 '19 at 03:43
  • i agree that `switch(true)` is an inappropriate use of switch. However, aside from that, case statements are cleaner and easier to read than `if...else` statements. – johny why May 04 '20 at 18:26
5

If you need check ranges you are probably better off with if and else if statements, like so:

if (range > 0 && range < 5)
{
    // ..
}
else if (range > 5 && range < 9)
{
    // ..
}
else
{
    // Fall through
}

A switch could get large on bigger ranges.

Kevin
  • 5,626
  • 3
  • 28
  • 41
3

No, this is not possible. The closest you can get is:

  switch(this.dealer) {
    case 1:
    case 2:
    case 3:
    case 4:
                      // DO SOMETHING
        break;
    case 5:
    case 6:
    case 7:
    case 8:
                      // DO SOMETHING
       break;

But this very unwieldly.

For cases like this it's usually better just to use a if/else if structure.

RoToRa
  • 37,635
  • 12
  • 69
  • 105
1

A more readable version of the ternary might look like:

var x = this.dealer;
alert(t < 1 || t > 11
  ? 'none'
    : t < 5
  ? 'less than five'
    : t <= 8
  ? 'between 5 and 8'
  : 'Between 9 and 11');
Brook Jordan
  • 1,223
  • 10
  • 18
-2

If you are trying to do something fast, efficient and readable, use a standard if...then...else structure like this:

var d = this.dealer;
if (d < 12) {
    if (d < 5) {
        alert("less than five");
    }else if (d < 9) {
        alert("between 5 and 8");
    }else{
        alert("between 9 and 11");
    }
}else{
    alert("none");
}

If you want to obfuscate it and make it awful (but small), try this:

var d=this.dealer;d<12?(d<5?alert("less than five"):d<9?alert("between 5 and 8"):alert("between 9 and 11")):alert("none");

BTW, the above code is a JavaScript if...then...else shorthand statement. It is a great example of how NOT to write code unless obfuscation or code minification is the goal. Be aware that code maintenance can be an issue if written this way. Very few people can easily read through it, if at all. The code size, however, is 50% smaller than the standard if...then...else without any loss of performance. This means that in larger codebases, minification like this can greatly speed code delivery across bandwidth constrained or high latency networks.

This, however, should not be considered a good answer. It is just an example of what CAN be done, not what SHOULD be done.

John Pace
  • 63
  • 2