Switch case with multiple values for the same case - flutter

I would like to know the syntax to set a multiple case statement in a switch / case.
For example :
String commentMark(int mark) {
switch (mark) {
case 0 : // Enter this block if mark == 0
return "Well that's bad" ;
case 1, 2, 3 : // Enter this block if mark == 1 or mark == 2 or mark == 3
return "Gods what happend" ;
// etc.
default :
return "At least you tried" ;
}
}
I cannot find the right syntax to set multiple case (the line case 1, 2, 3 :), is it even possible in Dart ?
I did not found any informations on pub.dev documentation, neither on dart.dev.
I tried :
case 1, 2, 3
case (1, 2, 3)
case (1 ; 2 ; 3)
case (1 : 2 : 3)
case 1 : 3
and more !

Execution continues until it reaches a break;. Therefore, you can list cases one after the other to get the following code execute on either one of those cases.
String commentMark(int mark) {
switch (mark) {
case 0 : // Enter this block if mark == 0
return "mark is 0" ;
case 1:
case 2:
case 3: // Enter this block if mark == 1 or mark == 2 or mark == 3
return "mark is either 1, 2 or 3" ;
// etc.
default :
return "mark is not 0, 1, 2 or 3" ;
}
}
The return statements above serve to get out of the function. If you do not want to return, you have to use break; after each block, of course. This code below is equivalent to the one above.
String commentMark(int mark) {
String msg;
switch (mark) {
case 0 : // Enter this block if mark == 0
msg = "mark is 0" ;
break;
case 1:
case 2:
case 3: // Enter this block if mark == 1 or mark == 2 or mark == 3
msg = "mark is either 1, 2 or 3" ;
break;
// etc.
default:
msg = "mark is not 0, 1, 2 or 3" ;
break; // this is a good habit, in case you change default to something else later.
}
return msg;
}

Instead of multiple case we can use or operator in single switch case it self.
switch (date) {
case 1 | 21 | 31:
return "st";
case 2 | 22:
return "nd";
case 3 | 23:
return "rd";
default:
return "th";
}

Related

I'm new to programming, is there a shorter way of achieving the same result using something like a case or caseif?

I have the code below written in my program, but I was wondering if someone could help me structure in a more summarized way as using 'case' or 'caseif' from other languages.
var imagePressed: UIImageView
imagePressed = self.redImage
if color == 1 {
imagePressed = self.redImage
}
if color == 2 {
imagePressed = self.orangeImage
}
if color == 3 {
imagePressed = self.yellowImage
}
if color == 4 {
imagePressed = self.greenImage
}
imagePressed.alpha = 0.5
I would suggest to use Dictionary to avoid much code:
let images = [1 : redImage, 2 : orangeImage, 3: yellowImage, 4: greenImage]
if let image = images[color] {
imagePressed = image
}
Also consider replacing hardcoded numbers with a enum for color e.g.:
enum Color {
case red
case orange
...
}
Swift also provides the switch statement.
You could simply type
var imagePressed: UIImageView
switch color {
case 1: imagePressed = self.redImage
case 2: imagePressed = self.orangeImage
case 3: imagePressed = self.yellowImage
case 4: imagePressed = self.greenImage
default: // provide any default value
}
Note that Swift switch statement has no implicit fallthrough. That mean, if any case is matching, the code flow breaks there.
Use comma-separated conditions to match multiple cases.
I recommend to read the switch statement in their language guide:
https://docs.swift.org/swift-book/LanguageGuide/ControlFlow.html#ID129
Your syntax is quite inefficient anyway because the code checks always all conditions even if color is 1.
A better form is if - else if
var imagePressed : UIImageView
imagePressed = self.redImage
if color == 1 {
imagePressed = self.redImage
} else if color == 2 {
imagePressed = self.orangeImage
} else if color == 3 {
imagePressed = self.yellowImage
} else if color == 4 {
imagePressed = self.greenImage
}
imagePressed.alpha = 0.5
In this particular case I recommend to use a switch statement and drop the extra variable
switch color {
case 1: self.redImage.alpha = 0.5
case 2: self.orangeImage.alpha = 0.5
case 3: self.yellowImage.alpha = 0.5
case 4: self.greenImage.alpha = 0.5
default: break
}

Algorithm on finding all 4 letter words in a string - where's the last item?

Posting a question here as ~find all ~4 letter words in a string ~algorithm site:stackoverflow.com google did not return any positive results.
The problem:
Write a function that takes a string of words and returns the number of 4 letter ones. The input argument 'sentence' is a string with words separated by spaces without punctuation.
So far I have a code like this:
func fourLetters(sentence: String) -> Int {
var targetNames = 0
var letterCount = 0
for letter in sentence {
if letter != " " {
letterCount += 1
} else {
print ("space found") // tech line
print (letterCount) // tech line
if letterCount == 4 {
targetNames += 1
letterCount = 0
}
letterCount = 0
}
}
print(targetNames) // tech line
return targetNames
}
The issue:
This algorithm now does not take into account the last part of the string giving the invalid number of 4 letter words. Consider we have the sentence: "Good Night Lil Peep" would return 1, although there are obviously two 4 teller words. What am I missing? Seems like the loop completely ignores the last word.
repl.it link for convenience and runs: https://repl.it/#DmitryAksyonov/4-lettered-names
Thank you for the help!
Regards
func findWords(ofLenght lenght: Int, in string: String) -> [Substring] {
let words = string.split{ $0.isWhitespace }
return words.filter { $0.count == lenght }
}
let input = "abcd word some string"
let result = findWords(ofLenght: 4, in: input)
print(result.count)
Output: 3
The problem is that the incrementation code for targetNames is encountered only if you find a space in the input string, which is not the case at the end of the string. You may be lucky if the last character of the string is a space.
So your code will fail even in the case where your sentence contains just one 4-letter word.
A possible solution is that you modify the condition of your first if statement by adding another condition to it which returns false if the loop has reached the end of the string, so that the else part of your code will run at that time and check if that last word is a 4-letter word.
Your algorithm doesn’t work because you don’t check for a 4-letter word at the end of the text.
You have to add another else clause and an index to check for end of text.
Of course there are more efficient ways to do that, it's just the answer to the question why the last item is not considered.
func fourLetters(sentence: String) -> Int {
var targetNames = 0
var letterCount = 0
var index = sentence.startIndex
for character in sentence {
sentence.formIndex(after: &index)
if character == " " { // check space
print ("space found") // tech line
print (letterCount) // tech line
if letterCount == 4 {
targetNames += 1
}
letterCount = 0
} else if index == sentence.endIndex { // check end of text
print ("end of text found") // tech line
letterCount += 1 // increment letterCount
if letterCount == 4 {
targetNames += 1
}
} else {
letterCount += 1
}
}
print(targetNames) // tech line
return targetNames
}
fourLetters(sentence: "Good Night Lil Peep") // 2

Swift 3 enum with associated value AND function comparison

I have this struct that has an enum property as well as a function:
struct UserInput {
enum State {
case unrestricted
case restricted(because: WarningType)
enum WarningType {
case offline
case forbidden
}
}
var config: UserInputConfig?
var state: State = .unrestricted
func isConfigured() -> Bool {
// Arbitrary checks about the config...
}
}
Is there a way to rewrite the following conditionals so that the check for isConfigured() and state are in the same statement?
if case .restricted = userInput.state {
return 1
} else if userInput.isConfigured() {
return 1
} else {
return 0
}
It seems because the State enum uses associated values, you cannot simply write if userInput.state == .restricted || userInput.isConfigured(), you need to use the if case syntax. There must be a way around this?
You would like to do this:
if case .restricted = userInput.state || userInput.isConfigured() {
return 1
} else {
return 0
}
but there is currently no way to do an OR with pattern matching. There are a couple of ways of doing AND.
By using DeMorgan's Laws, you can turn if a || b into if !(!a && !b) and by reversing the then and else clauses of your if statement, you can just check for if !a && !b.
Unfortunately, you can't say if !(case .restricted = userInput.state), but since your enum has only 2 cases, you can replace that with if case .unrestricted = userInput.state.
Now, how do you use that with another statement? You can't use && for the same reason you can't use ||.
You can check for the failing case by using a pattern that matches both failing conditions (which is using AND) and then return 1 if both failing conditions aren't met:
if case (.unrestricted, false) = (userInput.state, userInput.isConfigured()) {
return 0
} else {
return 1
}
Equivalently you can use a multi-clause condition:
if case .unrestricted = userInput.state, !userInput.isConfigured() {
return 0
} else {
return 1
}
In addition to being shorter and IMO easier to read, this second method can short circuit and skip calling userInput.isConfigured in the case where case .unrestricted = userInput.state fails.
You can do it really cleanly with a switch statement, and pattern matching:
switch userInput.state
{
case .unrestricted:
return userInput.isConfigured() ? 1 : 0;
case .restricted(_):
return 1
}

It is possible to do "if \(var1) = 0"?

var a = 0
(... up to var z = 0)
let letterchoosedbyplayer:String = LetterChoosed.text!
"LetterChoosed" is a textbox. The player enter a letter in this textbox.
I store the value in the variable "letterchoosedbyplayer".
Then i want to check if the variable called 'letterchoosedbyplayer' (it must be a letter of the alphabet) is equal to 1.
How can i do that?
I want to do that :
if \(letterchoosedbyplayer) = 1 {
}
Last Edit : All my code
let letterchoosedbyplayer:String = LetterChoosed.text!
if Int(letterchoosedbyplayer) == 1 {
print("vous avez perdu")
}
else {
switch letterchoosedbyplayer {
case "a":
print("lettre \(letterchoosedbyplayer) choisie")
a = 1
case "b":
print("lettre \(letterchoosedbyplayer) choisie")
b = 1
default:
print("cas défaut")
}
}
\() is used to append any object in a string. I don't think you can use this for your need
Try
if let letterchoosedbyplayer = LetterChoosed.text where letterchoosedbyplayer == "1" {
}
You could include the "1" case in the switch statement:
let letterchoosedbyplayer = LetterChoosed.text
if let lettrechoisie = letterchoosedbyplayer where !lettrechoisie.isEmpty {
switch lettrechoisie {
case "1": print("vous avez perdu")
case "a":
print("lettre \(lettrechoisie) choisie")
a = 1
case "b":
print("lettre \(lettrechoisie) choisie")
b = 1
default:
print("cas défaut")
}
}
Note that Int(letterchoosedbyplayer)! == 1 and letterchoosedbyplayer == "1" is the same thing.
Edit:
For your purpose you might use a dictionary rather than more than 20 single variables
var letterDict : [String : Int] = ["a" : 0, "b" : 0, "c" : 0, ... "z" : 0]
You can set a variable to 1 for example
letterDict["f"] = 1
Then you can check
if let lettrechoisie = letterchoosedbyplayer where !lettrechoisie.isEmpty {
let value = letterDict[lettrechoisie]!
if value == 1 {
// do something
} else {
// do something else
}
}
That avoids also a huge switch statement.

How do I increase the scope of variables in switch-case/loops in Swift?

How can I use switch case statements that creates variables/constants that are valid outside of the switch-case statement. If there is no way to do that, what else can I do to achieve the same effect i.e. creating variables subject to a condition, and make it accessible in "global" or higher scope?
var dogInfo = (3, "Fido")
switch dogInfo {
case(var age, "wooff"):
println("My dog Fido is \(age) years old")
case (3, "Fido"):
var matchtrue = 10 --> 10
matchtrue -->10
default:
"No match"
}
matchtrue --> Error: Use of unresolved identifier 'matchtrue'
HERE IS HOW I SOLVED IT:
var randomNumberOne = 0, randomNumberTwo = 0, randomNumberThree = 0
func chosen (#a: Int, #b: Int) -> (randomNumberOne: Int, randomNumberTwo: Int, randomNumberThree: Int){
if a > 0 {
let count1 = UInt32(stringArray1.count)-1
let randomNumberOne = Int(arc4random_uniform(count1))+1
}
if b > 0 {
let count2 = UInt32(stringArray2.count)-1 Output: 3 (from earlier)
let randomNumberTwo = Int(arc4random_uniform(count2))+1 Output: 2
}
if a > 0 && b > 0 {
let count3 = UInt32(stringArray3.count)-1
let randomNumberThree = Int(arc4random_uniform(count3))+1
}
return (randomNumberOne, randomNumberTwo, randomNumberThree)
}
chosen(a:0,b:1) Output: (.00,.12,.20)
Great now I can index with this into an array! Thank you!
There is no magic trick here. Swift uses block scoping and the switch creates a new scope to prevent errors and to show the programmer that the variables are only used in the scope. If you'd like to use the variables outside of the scope - declare these identifiers outside of the switch clause.
var dogInfo = (3, "Fido")
var matchtrue:Int = 0 // whatever you'd like it to default to
switch dogInfo {
case(var age, "wooff"):
println("My dog Fido is \(age) years old")
case (3, "Fido"):
matchtrue = 10 --> 10
matchtrue -->10
default:
"No match"
}
matchtrue --> 10
If matchtrue can contain a value or no value (if you do not initialize it) then you should use an optional variable declared before the switch:
var matchtrue: Int?
switch dogInfo {
...
case (3, "Fido"):
matchtrue = 10
...
}
if let matchtrue = matchtrue {
// matchtrue contains a non nil value
}
You cannot define a variable inside a switch case if you want to use it outside - it would be the same as declaring a variable in a block of code and accessing from outside:
if (test == true) {
var x = 10
}
println(x) // << Error: Use of unresolved identifier 'x'
Here's a way. Paste this in a playground. You supply an age and a name and the different cases identify a match and return a tuple which contains a Match text and a value of the match.
func dogMatch(age: Int, name: String) -> (Match: String, Value: Int) {
switch (age, name) {
case(age, "wooff"):
println("My dog Fido is \(age) years old")
return ("Match", 1)
case (3, "Fido"):
return ("Match", 10)
default:
return ("No Match", 0)
}
}
dogMatch(3, "Fido").Match
dogMatch(3, "Fido").Value