Switch Case: How to Use a Range Instead of a One Number

How can I use ranges in a switch case statement using JavaScript?

You have at least four options:

1. List each case

As shown by LightStyle, you can list each case explicitly:

switch(myInterval){

case 0:
case 1:
case 2:
doStuffWithFirstRange();
break;

case 3:
case 4:
case 5:
doStuffWithSecondRange();
break;

case 6:
case 7:
doStuffWithThirdRange();
break;

default:
doStuffWithAllOthers();
}

2. Use if / else if / else

If the ranges are large, that gets unwieldy, so you'd want to do ranges. Note that with if...else if...else if, you don't get to the later ones if an earlier one matches, so you only have to specify the upper bound each time. I'll include the lower bound in /*...*/ for clarity, but normally you would leave it off to avoid introducing a maintenance issue (if you include both boundaries, it's easy to change one and forget to change the other):

if (myInterval < 0) {
// I'm guessing this is an error
}
else if (/* myInterval >= 0 && */ myInterval <= 2){
doStuffWithFirstRange();
}
else if (/* myInterval >= 3 && */ myInterval <= 5) {
doStuffWithSecondRange();
}
else if (/* myInterval >= 6 && */ myInterval <= 7) {
doStuffWithThirdRange();
}
else {
doStuffWithAllOthers();
}

3. Use case with expressions:

JavaScript is unusual in that you can use expressions in the case statement, so we can write the if...else if...else if sequence above as a switch statement:

switch (true){

case myInterval < 0:
// I'm guessing this is an error
break;
case /* myInterval >= 0 && */ myInterval <= 2:
doStuffWithFirstRange();
break;

case /* myInterval >= 3 && */ myInterval <= 5:
doStuffWithSecondRange();
break;

case /* myInterval >= 6 && */ myInterval <= 7:
doStuffWithThirdRange();
break;

default:
doStuffWithAllOthers();
}

I'm not advocating that, but it is an option in JavaScript, and there are times it's useful. The case statements are checked in order against the value you give in the switch. (And again, lower bounds could be omitted in many cases because they would have matched earlier.) Even though the cases are processed in source-code order, the default can appear anywhere (not just at the end) and is only processed if either no cases matched or a case matched and fell through to the default (didn't have a break; it's rare you want to do that, but it happens).

4. Use a dispatch map

If your functions all take the same arguments (and that could be no arguments, or just the same ones), another approach is a dispatch map:

In some setup code:

var dispatcher = {
0: doStuffWithFirstRange,
1: doStuffWithFirstRange,
2: doStuffWithFirstRange,

3: doStuffWithSecondRange,
4: doStuffWithSecondRange,
5: doStuffWithSecondRange,

6: doStuffWithThirdRange,
7: doStuffWithThirdRange
};

Then instead of the switch:

(dispatcher[myInterval] || doStuffWithAllOthers)();

That works by looking up the function to call on the dispatcher map, defaulting to doStuffWithAllOthers if there's no entry for that specific myInterval value using the curiously-powerful || operator, and then calling it.

You can break that into two lines to make it a bit clearer:

var f = dispatcher[myInterval] || doStuffWithAllOthers;
f();

I've used an object for maximum flexibility. You could define dispatcher like this with your specific example:

var dispatcher = [
/* 0-2 */
doStuffWithFirstRange,
doStuffWithFirstRange,
doStuffWithFirstRange,

/* 3-5 */
doStuffWithSecondRange,
doStuffWithSecondRange,
doStuffWithSecondRange,

/* 6-7 */
doStuffWithThirdRange,
doStuffWithThirdRange
];

...but if the values aren't contiguous numbers, it's much clearer to use an object instead.

Switch case with range

This should work.

private func calculateUserScore() -> Int {
let diff = abs(randomNumber - Int(bullsEyeSlider.value))
switch diff {
case 0:
return PointsAward.bullseye.rawValue
case 1..<10:
return PointsAward.almostBullseye.rawValue
case 10..<30:
return PointsAward.close.rawValue
default:
return 0
}
}

It's there in the The Swift Programming Language book under Control Flow -> Interval Matching.

C# Switch Between Two Numbers?

Your syntax for trying to do a range with switch/case is wrong.

case 1 - 10: will be translated to case -9:

There are two ways you can attempt to cover ranges (multiple values):

List the cases individually

case 1: case 2: case 3: case 4: case 5:
case 6: case 7: case 8: case 9: case 10:
return "Number is 1 through 10";
default:
return "Number is not 1 though 10";

Calculate a range

int range = (number - 1) / 10;
switch (range)
{
case 0: // 1 - 10
return "Number is 1 through 10";
default:
return "Number is not 1 though 10";
}

HOWEVER

You really should consider covering ranges of values with an if statement

if (1 <= number && number <= 10)
return "Number is 1 through 10";
else
return "Number is not 1 through 10";

Switch case, check ranges in C# 3.5

You can use a HashTable respectively Dictionary to create a mapping of Condition => Action.

Example:

class Programm
{
static void Main()
{
var myNum = 12;

var cases = new Dictionary<Func<int, bool>, Action>
{
{ x => x < 3 , () => Console.WriteLine("Smaller than 3") } ,
{ x => x < 30 , () => Console.WriteLine("Smaller than 30") } ,
{ x => x < 300 , () => Console.WriteLine("Smaller than 300") }
};

cases.First(kvp => kvp.Key(myNum)).Value();
}
}

This technique is a general alternative to switch, especially if the actions consists only of one line (like a method call).

And if you're a fan of type aliases:

using Int32Condition = System.Collections.Generic.Dictionary<System.Func<System.Int32, System.Boolean>, System.Action>;
...
var cases = new Int32Condition()
{
{ x => x < 3 , () => Console.WriteLine("Smaller than 3") } ,
{ x => x < 30 , () => Console.WriteLine("Smaller than 30") } ,
{ x => x < 300 , () => Console.WriteLine("Smaller than 300") }
};

Using switch statement with a range of value in each case?

Java has nothing of that sort. Why not just do the following?

public static boolean isBetween(int x, int lower, int upper) {
return lower <= x && x <= upper;
}

if (isBetween(num, 1, 5)) {
System.out.println("testing case 1 to 5");
} else if (isBetween(num, 6, 10)) {
System.out.println("testing case 6 to 10");
}

Can I use a range of values in a single switch?

About the best you can do is something like this (see below). So in some cases (no pun intended :)), it's just better to use an if statement.

switch(card){
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
suit="Hearts";
break;
}

However, another approach you could consider is using a map.

Map<Integer, String> map = new HashMap<Integer, String>();
for (int i = 1; i <= 14; ++i) {
map.put(i, "Hearts");
}
for (int i = 15; i <= 26; ++i) {
map.put(i, "Clubs");
}

Then you can look up the card's suit using the map.

String suit1 = map.get(12); // suit1 will be Hearts after the assignment
String suit2 = map.get(23); // suit2 will be Clubs after the assignment


Related Topics



Leave a reply



Submit