swift case falling through - switch-statement

Does swift have fall through statement? e.g if I do the following
var testVar = "hello"
var result = 0
switch(testVal)
{
case "one":
result = 1
case "two":
result = 1
default:
result = 3
}
is it possible to have the same code executed for case "one" and case "two"?

Yes. You can do so as follows:
var testVal = "hello"
var result = 0
switch testVal {
case "one", "two":
result = 1
default:
result = 3
}
Alternatively, you can use the fallthrough keyword:
var testVal = "hello"
var result = 0
switch testVal {
case "one":
fallthrough
case "two":
result = 1
default:
result = 3
}

var testVar = "hello"
switch(testVar) {
case "hello":
println("hello match number 1")
fallthrough
case "two":
println("two in not hello however the above fallthrough automatically always picks the case following whether there is a match or not! To me this is wrong")
default:
println("Default")
}

case "one", "two":
result = 1
There are no break statements, but cases are a lot more flexible.
Addendum: As Analog File points out, there actually are break statements in Swift. They're still available for use in loops, though unnecessary in switch statements, unless you need to fill an otherwise empty case, as empty cases are not allowed. For example: default: break.

Here is example for you easy to understand:
let value = 0
switch value
{
case 0:
print(0) // print 0
fallthrough
case 1:
print(1) // print 1
case 2:
print(2) // Doesn't print
default:
print("default")
}
Conclusion: Use fallthrough to execute next case (only one) when the previous one that have fallthrough is match or not.

The keyword fallthrough at the end of a case causes the fall-through behavior you're looking for, and multiple values can be checked in a single case.

Related

Error in checking if a string only contains digits

let duration = "365460‬"
console.log((/^\d+$/.test(duration)))
Actual result: false
Expected result: true
But,
let duration = "11"
console.log((/^\d+$/.test(duration)))
Actual result: true
Expected result: true
What could be the problem? Please guide me
There's an extra character after 365460‬, and that's why your pattern does not match!
You can use the following to diagnose such issues in the future:
const duration = "365460‬";
for(let i = 0; i < duration.length; ++i) {
console.log(`Char at index ${i}: ${duration[i]} | Unicode: ${duration.charCodeAt(i)}`);
}
As you may observe from the result of the above code, there is a character with unicode value 8236, which is some sort of formatting character known as "Pop Directional Formatting".
https://www.codetable.net/decimal/8236
There is a unicode character at the end of the string which makes result false.
duration = "365460‬"
console.log(duration.split(""));
console.log(duration.length); // 7 instead of 6
isdigit(str) {
let pattern = /^\d+$/
if (str.match(pattern)) {
return true
} else {
return false
}
}
You can use the above function it solves the problem of detecting only numbers.
You can use isNaN() instead which would be the relevant syntax in your case

Switch statement bigger than

How to make a switch statement condition look like this:
if(age>18)
I want it to look like this, but then in a switch-statement version.
Is this possible?
Depends on the language you use.
C# => Not possible: switch case
Each case label specifies a constant value.
Java => Not possible: switch case
An if-then-else statement can test expressions based on ranges of
values or conditions, whereas a switch statement tests expressions
based only on a single integer
You will have to use an if-elseif-elseif-else approach in case you use Java or C#.
Javascript => Possible: switch case
case expressionN A case clause used to match against expression.
switch (true) {
case age > 18:
document.write("You are older than 18");
break;
}
mostly the switch statements are used when you are exactly matching the phrase.
switch (age>18)
{
case true:
//Do something
break;
case false:
//Do something
break;
}
In your case use if condition.It will also gives you better way to check your data.If your age is less than 18 or any other case.
if(age>18)
{/* Do something if your condition is true */ }
else
{ /* When your condition is false */ }
Yes, it's possible with a sort of 'reverse condition' trick - if that's supported by the language used, of course. That's how it looks in JavaScript:
function checkAge(age) {
switch (true) {
case age < 18:
console.log('Really young');
break;
case age < 25:
console.log('Young and proud');
break;
case age < 32:
console.log('Mature and proud');
break;
default:
console.log('Well, I got some news for you...');
}
}
checkAge(17); // Really young
checkAge(24); // Young and proud
checkAge(31); // Mature and proud
The trick is that each subsequent case value is checked against the expression specified as switch value. Still, as you need to delimit each section with break, I really doubt that's more readable than if-else statement.
You haven't specified a language, but the below construct is possible in languages which take an expression in the switch, viz:
switch (age>18)
{
case true:
// Do over 18 stuff here
break;
case false:
// Do under 18 stuff here
break;
}
Although this works, this wouldn't be an intuitive branching technique so readability of the code may suffer - use of if / then else for branches, or the conditional operator for conditional evaluation would be more common.
in php you can do:
switch($age) {
case ($age < 17):
print "do something";
break;
case ($age > 18): print "over 18"; break;
}
Technically you can put it like that (C# code sample):
switch (age) {
case 0:
case 1:
case 2:
...
case 18:
break;
default: // <- if(age>18)
...
break;
}
but do you really want it? In C#, Java etc. we usually use if else:
if (age <= 5) { // from 0 up to 5
...
}
else if (age <= 10) { // from 5 up to 10
...
}
else if (age <= 18) { // from 10 up to 18
...
}
else { // over 18
...
}
In case of a SQL dialect (where often you don't have if construction) you can put it like that:
case
when (age > 18) then
...
else...
end
for instance
select case
when (age > 18) then
'Over 18'
else
'18 or under 18'
end
from MyTable

Javascript: on/off switch

What is wrong whith this code? I have tested it many times but something still doesn't work.
var playernow = 1; //Whose player's turn it is (1 or 2)
function bobenli(playernow){
var wert="";
switch (playernow){
case "1":
wert="X";
playernow=2;
case "2":
wert="O";
playernow=1;
}
alert(playernow);
}
No break statement, both cases get executed. Also as others have said you are comparing ints to strings. You can drop the quotes in the cases.
var playernow = 1; //Welcher Spieler dran ist )(1 oder 2)
function bobenli(playernow){
var wert="";
switch (playernow){
case 1:
wert="X";
playernow=2;
break;
case 2:
wert="O";
playernow=1;
break;
}
alert(playernow);
}
var playernow = 1; //Welcher Spieler dran ist )(1 oder 2)
function bobenli(playernow){
var wert="";
switch (playernow){
case "1":
wert="X";
playernow=2;
break;
case "2":
wert="O";
playernow=1;
break;
}
alert(playernow);
}
you missed break statement in following switch case... http://jsfiddle.net/yjusC/
You need a break at the end of each case:
switch (playernow){
case "1":
wert="X";
playernow=2;
break;
case "2":
wert="O";
break;
First: no break, second: you're comparing different types (int and string). This might have no impact now, but you should be careful in general.
case "1": // This is looking for a string. You set playernow equal to an integer value above.

Is There a Groovier Way To Add Dashes to a String?

I have the following code, which works, but I'm wondering if there is a "groovier" way of doing this:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
* */
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
def part1 = isbn.substring(0, 1)
def part2 = isbn.substring(1, 7)
def part3 = isbn.substring(7, 9)
def part4 = isbn.substring(9, 10)
return "${part1}-${part2}-${part3}-${part4}"
} else if (isbn?.length() == 13) {
def part1 = isbn.substring(0, 3)
def part2 = isbn.substring(3, 4)
def part3 = isbn.substring(4, 10)
def part4 = isbn.substring(10, 12)
def part5 = isbn.substring(12, 13)
return "${part1}-${part2}-${part3}-${part4}-${part5}"
} else {
return isbn
}
}
You could first use the [] string operator to get the substrings instead of substring and drop the intermediate variables. For example in the case for length == 10:
"${isbn[0]}-${isbn[1..6]}-${isbn[7..8]}-${isbn[9]}"
Now, there is a bit of repetition there. You can get instead first get all the isbn segments and then .join them with '-':
[isbn[0], isbn[1..6], isbn[7..8], isbn[9]].join('-')
And, even further, instead of referencing isbn every time, you can make a list of the ranges you want to get and then get them all the same time using collect:
[0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
If you're going for code golfing, you can also do:
('-'+isbn)[1, 0, 2..7, 0, 8..9, 0, 10]
I'll leave it to you to figure out how that works, but i guess it's probably not a good idea to leave that on production code, unless you want to surprise future maintainers hehe.
Also, notice that the format when length == 13 is the same as for length == 10 but with a different prefix, you can then reuse the same function in that case. The whole function (with a couple of tests) would be:
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
**/
def formatIsbn(isbn) {
switch (isbn?.length()) {
case 10: return [0, 1..6, 7..8, 9].collect { isbn[it] }.join('-')
case 13: return isbn.take(3) + '-' + formatIsbn(isbn.drop(3))
default: return isbn
}
}
assert formatIsbn('abcdefghij') == 'a-bcdefg-hi-j'
assert formatIsbn('abcdefghijklm') == 'abc-d-efghij-kl-m'
Now, i think there are some bad smells in that code. Can isbn be null? At least to me, this doesn't look like a function that needs to bother about the nullity of its argument, or at least that's not clear by reading its name (it should be called something like formatIsbnOrNull instead if both ISBN strings and null values are accepted). If null values are not valid, then let it blow up with a NullPointerException when accessing isbn.length() so the caller know they have passed a wrong argument, instead of silently returning the same null.
The same goes for the return ISBN at the end. Is it expected for that function to receive a string that's neither 10 nor 13 characters long? If not, better throw new IllegalArgumentException() and let the caller know they have called it wrongly.
Finally, i'm not sure if this is the most "readable" solution. Another possible solution is having a string for the format, like '###-#-######-##-#' and then replace the #s by the isbn characters. I think it might be more self-documenting:
def formatIsbn(isbn) {
def format = [
10: '#-######-##-#',
13: '###-#-######-##-#'
][isbn.length()]
def n = 0
format.replaceAll(/#/) { isbn[n++] }
}
Consider adding the method to the String class, as shown here. Note that this answer is a spin on a clever suggestion in epidemian's answer (re: collect).
Note:
This code augments String with asIsbn().
The range [0..2] does not need the call to asIsbn(), but the symmetry of using collect twice is irresistable.
Groovy returns the last expression in if/else, so 'return' is not necessary
/**
* 10 digit - #-######-##-#
* 13 digit - ###-#-######-##-#
**/
String.metaClass.asIsbn = { ->
if (delegate.length() == 10) {
[0, 1..6, 7..8, 9].collect { delegate[it] }.join('-')
} else if (delegate.length() == 13) {
[0..2, 3..12].collect { delegate[it].asIsbn() }.join('-')
} else {
delegate
}
}
assert "abcdefghij".asIsbn() == 'a-bcdefg-hi-j'
assert "abcdefghijklm".asIsbn() == 'abc-d-efghij-kl-m'
assert "def".asIsbn() == "def"
String s = null
assert s?.asIsbn() == null
I would try using Regex... I think it's pretty much readable if you know how to use regex, and it's javascript inspired syntax in groovy is pretty cool also.
One more thing: it's pretty clear, looking at the capture groups, what your string looks like for the desired formatting.
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
m = isbn =~ /(\d{1})(\d{6})(\d{2})(\d{1})/
return "${m[0][1]}-${m[0][2]}-${m[0][3]}-${m[0][4]}"
} else if (isbn?.length() == 13) {
m = isbn =~ /(\d{3})(\d{1})(\d{6})(\d{2})(\d{1})/
return "${m[0][1]}-${m[0][2]}-${m[0][3]}-${m[0][4]}-${m[0][5]}"
} else {
return isbn
}
}
Btw, #epidemian suggestion using backreferences is great! I think the code would look like:
private formatISBN(String isbn) {
if (isbn?.length() == 10) {
return isbn.replaceAll(/(\d{1})(\d{6})(\d{2})(\d{1})/, '$1-$2-$3-$4')
} else if (isbn?.length() == 13) {
return isbn.replaceAll(/(\d{3})(\d{1})(\d{6})(\d{2})(\d{1})/, '$1-$2-$3-$4-$5')
} else {
return isbn
}
}
Dunno if I like this any better. I'd make the position map a static final, too.
private isbnify(String isbn) {
def dashesAt = [ 10: [[0,1], [1,7], [7,9], [9,10]],
13: [[0,3], [3,4], [4,10], [10,12], [12,13]]]
def dashes = dashesAt[isbn?.length()]
(dashes == null) ? isbn
: dashes.collect { isbn.substring(*it) }.join('-')
}
Ranges make for a bit less clutter, IMO:
private isbnify3(String isbn) {
def dashesAt = [ 10: [0, 1..6, 7..8, 9],
13: [0..2, 3, 4..9, 10..11, 12]]
def dashes = dashesAt[isbn?.length()]
dashes == null ? isbn : dashes.collect { isbn[it] }.join("-")
}
With an inject-with-two-accumulators it should be easy to do a list-of-dash-positions version, too.
This should be a comment to #everton, but I don't have the 50 reputation needed to do that yet. So this answer is really just a suggested variation on #everton's answer.
One less regex by making the first 3 digits optional. The downside is having to remove a leading '-' if the ISBN is 10 characters. (I also prefer \d over \d{1}.)
private formatISBN(String isbn) {
String result = isbn.replaceAll(/^(\d{3})?(\d)(\d{6})(\d{2})(\d)$/,
'$1-$2-$3-$4-$5')
if (result) {
return result.startsWith('-') ? result[1..-1] : result
} else {
return isbn // return value unchanged, pattern didn't match
}
}
println formatISBN('1234567890')
println formatISBN('9991234567890')
println formatISBN('123456789') // test an ISBN that's too short
println formatISBN('12345678901234') // test an ISBN that's too long

Can I jump from one case to another in a switch statements?

For switch statements, is it possible to change the value of the switch inside the switch statement so that it can jump around to different cases?
Ex:
int w = 0;
switch(w)
{
case 1:
doSomething();
w = 3;
case 2:
doSomething();
break;
case 3:
doSomething();
break;
}
Basically what I'm asking is, if I do not place a break statement for a case and I change the value of the switch in the same case, will the code execute both cases?
Yes you can change the value inside switch but it will not execute case for new value until you break in the case where you changed the value.
In your case it will not go in any case as there is no case for 0. But if you change to w = 1 then it will go for case 1 and then for case 2 as you do not have break; but it will not go for case 3.
No, it will not change and will not execute new case statement.
Remember that, once appropriate match is found with the case statement corresponding to a value inside the switch statement, that particular case is executed and once that is executed ( if break is provided after each case to prevent falling through all cases) , then the control returns to the end of switch statement.
Sample Code :
public class A {
public static void main(String [] args) {
int i=1;
switch(i) {
case 1 :
System.out.println("Case 1");
i = 2;
break;
case 2 :
System.out.println("Changed to Case 2");
break;
default:
System.out.println("Default");
break;
}
System.out.println("Final value of i " + i);
}
}
Output :
Case 1
Final value of i 2
Note : Inserting proper breakpoints, try to debug. You will come to know yourself, what exactly is happening.
If we do not give break after each case then Java will start executing the statement from matching case and keep on executing statements for following cases as well, until either a break statement is found or switch statements end is encountered.
If case 1 happens to execute, it's just a fall through to the case 2. And since there is a break in case 2, further fall through doesn't happen. It doesn't jump to case 3 because of the statement w = 3 ; in case 1.
No the switch's case will not change when changing the value in a particular case it checks only once
let a = 1
switch (a) {
case 1:
console.log("Hello from 1")//only this will be printed
a = 2//value of a is changed
break
case 2:
console.log("hello from 2")//this will not execute
a = 3
break
case 3:
console.log("hello from 3")//this will not execute
a = 4
break
case 4:
console.log("hello from 4")//this will not execute
break
default:
console.log("default")
}
console.log(a)//value will be 2

Resources