Expression inside switch case statement
amount
is a number, but the expressions in the case
clauses only evaluate to booleans; the values will never match.
You could always do
switch (true) {
case (amount >= 7500 && amount < 10000):
// Code
break;
case (amount >= 10000 && amount < 15000):
// Code
break;
// etc.
}
It works because the value being matched is now the boolean true
, so the code under the first case
clause with an expression that evaluates to true
will be executed.
It’s kinda “tricky”, I guess, but I see nothing wrong with using it. A simple if
–else
statement would probably be more concise, and you’d not have to worry about accidental fall-through. But there it is anyway.
Having same expression inside case in switch statement
Both expressions 'a' && 1
and 'b' && 1
have the value 1
.
Therefore your code is strictly equivalent to this:
...
switch(c){
case 1: printf("Hello");
case 1: printf("hey");
break;
default : printf("Goodbye");
}
}
...
Hence the error message because two or more case labels cannot have the same value. The C language does not allow this.
Can I match on different parts of an expression in a switch case?
You could use String#matches
here with if-else logic:
if (s.matches("ABC.*")) {
// do something
{
else if (s.matches("AB.*")) {
// do something else
}
else if (s.matches("A.*")) {
// do something else
}
else {
// no match
}
Note that we check for the more specific match first, and then fallback to capturing less specific matches. If we checked in the reverse order, then both ABC
and ABD
would be caught with the starts with A
logic, and the more specific matches would not happen.
How can you use comparisons in switch statements?
let a = 2, b = 5;
switch(true){
case a>b:
console.log('do something here');
break;
default:
console.log('do something there');
break;
}
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 case
s are processed in source-code order, the default
can appear anywhere (not just at the end) and is only processed if either no case
s 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.
JavaScript: using a condition in switch case
This works:
switch (true) {
case liCount == 0:
setLayoutState('start');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount<=5 && liCount>0:
setLayoutState('upload1Row');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount<=10 && liCount>5:
setLayoutState('upload2Rows');
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
case liCount>10:
var api = $('#UploadList').data('jsp');
api.reinitialise();
break;
}
The only thing necessary is switch(true){...}
and for your case expressions to evaluate to booleans.
It works because, the value we give to the switch is used as the basis to compare against. Consequently, the case expressions, also evaluating to booleans will determine which case is run. Could also turn this around, and pass switch(false){..}
and have the desired expressions evaluate to false instead of true.. but personally prefer dealing with conditions that evaluate to truthyness. However, it does work too, so worth keeping in mind to understand what it is doing.
Eg: if liCount is 3, the first comparison is true === (liCount == 0)
, meaning the first case is false. The switch then moves on to the next case true === (liCount<=5 && liCount>0)
. This expression evaluates to true, meaning this case is run, and terminates at the break
. I've added parentheses here to make it clearer, but they are optional, depending on the complexity of your expression.
It's pretty simple, and a neat way (if it fits with what you are trying to do) of handling a long series of conditions, where perhaps a long series of ìf() ... else if() ... else if () ...
might introduce a lot of visual noise or fragility.
Use with caution, because it is a non-standard pattern, despite being valid code.
Using two values for one switch case statement
You can use have both CASE
statements as follows.
case text1:
case text4:{
//blah
break;
}
SEE THIS EXAMPLE:The code example calculates the number of days in a particular month:
class SwitchDemo {
public static void main(String[] args) {
int month = 2;
int year = 2000;
int numDays = 0;
switch (month) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
numDays = 31;
break;
case 4:
case 6:
case 9:
case 11:
numDays = 30;
break;
case 2:
if (((year % 4 == 0) &&
!(year % 100 == 0))
|| (year % 400 == 0))
numDays = 29;
else
numDays = 28;
break;
default:
System.out.println("Invalid month.");
break;
}
System.out.println("Number of Days = "
+ numDays);
}
}
This is the output from the code:
Number of Days = 29
FALLTHROUGH:
Another point of interest is the break statement. Each break statement
terminates the enclosing switch statement. Control flow continues with
the first statement following the switch block. The break statements
are necessary because without them, statements in switch blocksfall
: All statements after the matching case label are executed in
through
sequence, regardless of the expression of subsequent case labels,
until a break statement is encountered.
EXAMPLE CODE:
public class SwitchFallThrough {
public static void main(String[] args) {
java.util.ArrayList<String> futureMonths =
new java.util.ArrayList<String>();
int month = 8;
switch (month) {
case 1: futureMonths.add("January");
case 2: futureMonths.add("February");
case 3: futureMonths.add("March");
case 4: futureMonths.add("April");
case 5: futureMonths.add("May");
case 6: futureMonths.add("June");
case 7: futureMonths.add("July");
case 8: futureMonths.add("August");
case 9: futureMonths.add("September");
case 10: futureMonths.add("October");
case 11: futureMonths.add("November");
case 12: futureMonths.add("December");
default: break;
}
if (futureMonths.isEmpty()) {
System.out.println("Invalid month number");
} else {
for (String monthName : futureMonths) {
System.out.println(monthName);
}
}
}
}
This is the output from the code:
August
September
October
November
December
Using Strings in switch Statements
In Java SE 7 and later, you can use a String object in the switch
statement's expression. The following code example, ,
displays the number of the month based on the value of the String
named month:
public class StringSwitchDemo {
public static int getMonthNumber(String month) {
int monthNumber = 0;
if (month == null) {
return monthNumber;
}
switch (month.toLowerCase()) {
case "january":
monthNumber = 1;
break;
case "february":
monthNumber = 2;
break;
case "march":
monthNumber = 3;
break;
case "april":
monthNumber = 4;
break;
case "may":
monthNumber = 5;
break;
case "june":
monthNumber = 6;
break;
case "july":
monthNumber = 7;
break;
case "august":
monthNumber = 8;
break;
case "september":
monthNumber = 9;
break;
case "october":
monthNumber = 10;
break;
case "november":
monthNumber = 11;
break;
case "december":
monthNumber = 12;
break;
default:
monthNumber = 0;
break;
}
return monthNumber;
}
public static void main(String[] args) {
String month = "August";
int returnedMonthNumber =
StringSwitchDemo.getMonthNumber(month);
if (returnedMonthNumber == 0) {
System.out.println("Invalid month");
} else {
System.out.println(returnedMonthNumber);
}
}
}
The output from this code is 8.
FROM Java Docs
OR operator in switch-case?
What are the backgrounds for a switch-case to not accept this operator?
Because case
requires constant expression as its value. And since an ||
expression is not a compile time constant, it is not allowed.
From JLS Section 14.11:
Switch label should have following syntax:
SwitchLabel:
case ConstantExpression :
case EnumConstantName :
default :
Under the hood:
The reason behind allowing just constant expression with cases can be understood from the JVM Spec Section 3.10 - Compiling Switches:
Compilation of switch statements uses the tableswitch and lookupswitch instructions. The tableswitch instruction is used when the cases of the switch can be efficiently represented as indices into a table of target offsets. The default target of the switch is used if the value of the expression of the switch falls outside the range of valid indices.
So, for the cases label to be used by tableswitch
as a index into the table of target offsets, the value of the case should be known at compile time. That is only possible if the case value is a constant expression. And ||
expression will be evaluated at runtime, and the value will only be available at that time.
From the same JVM section, the following switch-case
:
switch (i) {
case 0: return 0;
case 1: return 1;
case 2: return 2;
default: return -1;
}
is compiled to:
0 iload_1 // Push local variable 1 (argument i)
1 tableswitch 0 to 2: // Valid indices are 0 through 2 (NOTICE This instruction?)
0: 28 // If i is 0, continue at 28
1: 30 // If i is 1, continue at 30
2: 32 // If i is 2, continue at 32
default:34 // Otherwise, continue at 34
28 iconst_0 // i was 0; push int constant 0...
29 ireturn // ...and return it
30 iconst_1 // i was 1; push int constant 1...
31 ireturn // ...and return it
32 iconst_2 // i was 2; push int constant 2...
33 ireturn // ...and return it
34 iconst_m1 // otherwise push int constant -1...
35 ireturn // ...and return it
So, if the case
value is not a constant expressions, compiler won't be able to index it into the table of instruction pointers, using tableswitch
instruction.
How do use a Switch Case Statement in Dart
The comparsion of double values using '==' is not very reliable and should be avoided (not only in Dart but in most languages).
You could do something like
methodname(num radians) {
// you can adjust this values according to your accuracy requirements
const myPI = 3142;
int r = (radians * 1000).round();
switch (r) {
case 0:
// do something
break;
case myPI:
// do something else
break;
}
}
This question contains some additional information that might interest you
- comparing float/double values using == operator
- How should I do floating point comparison?
some more information:
- https://www.dartlang.org/docs/spec/latest/dart-language-specification.html#h.50ae78s6gbw2
- http://floating-point-gui.de/errors/comparison/
Related Topics
React: Script Tag Not Working When Inserted Using Dangerouslysetinnerhtml
Why Don't Audio and Video Events Bubble
How to Get HTML Elements from an Object Tag
Retrieving File Names Out of a Multi-File Upload Control with JavaScript
JavaScript Variables in HTML Attributes
What's a Good Way to Extend Error in JavaScript
Accessing Redux State in an Action Creator
Web Workers Without a Separate JavaScript File
How to Custom-Format the Autocomplete Plug-In Results
Getting a Better Understanding of Callback Functions in JavaScript
Change <Select>'s Option and Trigger Events with JavaScript
How to Determine Which HTML Page Element Has Focus
Flow 2 Columns of Text Automatically with CSS
How to Draw a Line Between Two Divs
Finding Matches Between Multiple JavaScript Arrays
Are All JavaScript Callbacks Asynchronous? If Not, How to Know Which Are
Calling a JavaScript Function Returned from an Ajax Response