Adding to Dictionary inside a For Loop - swift

I'm working with a swift playground for a project at Treehouse. I'm having trouble with adding an additional key:value pair to a dictionary inside of a for loop. Here is the code that I have:
var counter = 0
for (var player) in experiencedPlayers {
counter += 1
if counter % 3 == 0 {
for team in 1...3 {
switch team {
case 1:
teamSharks.append(player)
player["Team"] = "Sharks"
case 2:
teamDragons.append(player)
player["Team"] = "Dragons"
case 3:
teamRaptors.append(player)
player["Team"] = "Raptors"
default: break
}
}
}
}
This method does not error out, but it should be adding "Team": "Sharks", etc. to the player's dictionary but it is not. Any suggestions?

You need to modify player before appending player.
switch team {
case 1:
player["Team"] = "Sharks"
teamSharks.append(player)
case 2:
player["Team"] = "Dragons"
teamDragons.append(player)
case 3:
player["Team"] = "Raptors"
teamRaptors.append(player)
default: break
}
}
This is because player is a value type.
Note that will not have any effect on the data stored in experiencedPlayers, only the teamSharks, etc. arrays.

Because player is declared inside the scope in your for..in only. So as soon as you try to modify it it will work only inside this scope, it's like a copy. If you want to modify you need to reassign your player in your experiencedPlayers with your modified object

Related

Custom Set of Steps in Slider

I have a #StateObject Slider. It is set to slide 1...5 step 1.
I need to have custom step [1,2,5,10,20] instead of step 1.
I have a setup where I have the slider work as an array index to my array of custom step. It is working. But It is jerky. Single slide registers slide value dozen times making my array to get picked up dozen times jerking the process. How can I have custom steps smooth.
I can adjust within the app but if Slider provides the exact number, logic of the app become much cleaner. Less translation, clear the logic.
Slider(value: $tSlider, in: 1...5, step: 1)
// How can I make above like below
Slider(value: $tSlider, in: 1...5, step: [1,2,5,10,20]
// What I have currently
#Published var tSteps:[Int] = [1,2,5,10,20]
#Published var tSlider: Double = 1
var tScale: Int { return tlSteps[Int(tlSlider)-1] }
Setting steps on Slider was a bad idea. Stepper was correct choice.
Stepper("Year Scale", onIncrement: {
switch tVM.tlScale {
case 1: self.tlScale = 2
case 2: self.tlScale = 5
case 5: self.tlScale = 10
case 10: self.tlScale = 20
default: self.tlScale = 20
},
onDecrement: {
switch tVM.tlScale {
case 20: self.tlScale = 10
case 10: self.tlScale = 5
case 5: self.tlScale = 2
case 2: self.tlScale = 1
default: self.tlScale = 1
}
})
referred to : post here and Skipjakk's answer. Strange Behavior of Stepper in SwiftUI

Switch statement where value is Int but case can contain array [duplicate]

This question already has answers here:
Swift switch pattern matching with arrays
(3 answers)
Closed 6 years ago.
I want to put my array of values as a case for my switch statement
I have an array of values say
let intValues = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20 .... 100]
and I want to use a switch statement to be used as a comparison tool like so.
let inputValue = 30 // or some other int value
switch inputValue {
case 101:
// do something lol
/* =============================== */
case intValues: //
// do something more:
/* =============================== */
case 13131:
// do another thing
default:
// do default
}
I know I can do this easily by either doing this case 1, 2, 3, 4, 5, and so on or by using an if statement like so:
if intValues.contains(inputValue) {
// do something more:
} else if inputValue == 101 {
// do something lol
} else if inputValue == 13131 {
// do another thing
} else {
// do default
}
or by doing somethig like
if intValues.contains(inputValue) {
// do something more:
} else {
switch inputValue {
case 101:
// do something lol
case 13131:
// do another thing
default:
// do default
}
}
and vice versa
But is it possible though? to do it with just a switch statement?
You can use case let with where for that.
let intValues = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20]
let inputValue = 30 // or some other int value
switch inputValue {
case let x where intValues.contains(x):
// do something more:
case 101:
// do something lol
case 13131:
// do another thing
default:
// do default
}
You can do this with range operator.
let inputValue = 30
switch value {
case 1...100:
print("between hundred")
case 101:
print("it's 101")
default:
print("outer value")
}
You should just use a countable closed range in your switch cases:
let inputValue = 30
switch inputValue {
case 1...10:
print(1...10)
case 11...20:
print(11...20)
case 21...100:
print(21...100) // "21...100\n"
default:
print("default")
}

Swift correct break multi-layer switch

I'm rewriting a code from java to swift and need to break a multi-layered switches right way. In Java it looks like :
block0 : switch (topSwithch) {
case one: {
switch (innerSwitch) {
case insideCase: {
if (something){
break block0;
}
// etc
So, I'm breaking one switch from another. How do I do it in swift ?
This is what it'd look like in Swift. I did this in a playground with hardcoded values for the variables:
let topSwitch = 1
let innerSwitch = 4
let one = 1
let insideCase = 4
let something = true
block0 : switch (topSwitch) { //first switch labeled "block0", switching on topSwitch
case one: //topSwitch is 1, one is 1
switch (innerSwitch) { // switching on innerSwitch
case insideCase: // both are 1
if (something){ // if true
break block0; // break from "block0"
}
default: break // else
}
default: break // else
}

Binary operator '~=' cannot be applied to two UmRet operands

I'm working on integrating an IDTech swiper into my app and I've gotten pretty far along, added the library, registered notifications, unregistered them, and now I'm working on a function that connects the reader. I can't seem to figure out what I'm doing wrong here when I'm attempting to switch cases based on a return value.. could someone please help me?
func displayUmRet(operation: String, returnValue: UmRet) {
var string = ""
do {
switch returnValue {
case UMRET_SUCCESS: string = ""
case UMRET_NO_READER: string="No reader attached"
case UMRET_SDK_BUSY: string="Communication with reader in progress"
case UMRET_MONO_AUDIO: string="Mono audio enabled"
case UMRET_ALREADY_CONNECTED: string="Already connected"
case UMRET_LOW_VOLUME: string="Low volume"
case UMRET_NOT_CONNECTED: string="Not connected"
case UMRET_NOT_APPLICABLE: string="Not applicable to reader type"
case UMRET_INVALID_ARG: string="Invalid argument"
case UMRET_UF_INVALID_STR: string="Invalid firmware update string"
case UMRET_UF_NO_FILE: string="Firmware file not found"
case UMRET_UF_INVALID_FILE: string="Invalid firmware file"
default: string="<unknown code>"
}
} while (0)
// var retStatus = UMRET_SUCCESS==ret
//self.textResponse.text = "\(operation), \(retStatus), \(string)"
self.hexResponse.text = "";
}
You need to put a . before your cases:
enum UmRet {
case UMRET_SUCCESS, UMRET_FAILURE
}
var string = " "
let returnValue = UmRet.UMRET_SUCCESS
switch returnValue {
case .UMRET_SUCCESS: string = "y"
case .UMRET_FAILURE: string = "n"
}
Also, 0 isn't the same as false in Swift, so:
do {
...
} while (0)
Shouldn't work either.
And you don't need semicolons at the end of a line, so this:
self.hexResponse.text = "";
can be this:
self.hexResponse.text = ""
And finally, if your switch statement has every case for every case in your enum, you don't need a default case. (that's why mine didn't have one in the example)
By the way, ~= is just the operator for the pattern-matching function, which is what Swift does in a switch statement. It works kind of like the == function, for instance, Int ~= Int is the same as Int == Int. But it's a bit more versatile: for instance Range ~= Int, eg 0...3 ~= 2 returns whether or not the Int is in the range. (So true in this case) For enums, it matches cases to cases. In my example, it'll match UMRET_SUCCESS, and string will be set to y.

Cannot change tuple in an array

I'm trying to change a tuple in an array , however ,when I try
emo = (type:emo.type,strength:increaseStrength(emo.strength))
it gives me error
"cannot assign to 'let' value 'emo'
here is my code :
var emotions : [(type : String, strength: Int)] = [("happy",0),("scared",0),("tender",0),("excited",0),("sad",0)]
func increaseStrength(i:Int)->Int {
switch i {
case 0: return 1
case 1: return 2
case 2: return 3
case 3: return 0
default :return 0
}
}
#IBAction func HappyBA(sender: AnyObject) {
for emo in emotions {
if (emo.type == "happy" ){
emo = (type:emo.type,strength:increaseStrength(emo.strength))
}
}
println(emotions)
}
If there are better way to do the assignment please tell me I am so appreciated ! Thanks..
There is no point assigning to emo even if you could do it. This is not the same as replacing the corresponding object in the array - which is what you do want to do. emo is a copy; even if you were to set a property of it, it wouldn't affect the one back in the array. And certainly setting the variable would not magically read back into the array!
Here's one solution. Instead of cycling thru emotions in your for-loop, cycle thru enumerate(emotions). Now you have a tuple of an index number along with an emotion. If this is the right emotion type, write into the array via the index number.
for (ix,emo) in enumerate(emotions) {
if emo.type == "happy" {
emotions[ix] = (type:emo.type,strength:increaseStrength(emo.strength))
}
}
Or you could use map.
emotions = emotions.map {
emo in
if emo.type == "happy" {
return (type:emo.type,strength:increaseStrength(emo.strength))
} else {
return emo
}
}