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.
Related
Swift character is so hard to manipulate..
I have a simple request:
For a given string, I'd like to encode it with a "moving integer" for all the alphabetical digits.
For example: "abc", move 1: would become "bcd"; "ABC", move 1 -> "BCD".
One thing to note is, if after moving, the range it larger than "z" or "Z", it should loop back and calculate from "a" or "A" again. e.g "XYZ", move 1 -> "YZA"
This would be very easy to do in Java. But could anyone show me what would be the cleanest way to do it swift?
I've done something like:
let arr: [Character] = Array(s)
for i in arr {
let curAsciiValue = i.asciiValue!
var updatedVal = (curAsciiValue + UInt8(withRotationFactor))
if i >= "A" && i <= "Z" {
newAsciiVal = 65
updatedVal = updatedVal - 65 >= 26 ? 65 + (updatedVal - 65) % 26 : updatedVal
} else if i >= "a" && i <= "z" {
newAsciiVal = 97
updatedVal = updatedVal - 97 >= 26 ? 97 + (updatedVal - 97) % 26 : updatedVal
}
}
What should be best way to do this?
Better to bring all your logic together extending the Character type:
extension Character {
var isAlphabet: Bool { isLowercaseAlphabet || isUppercaseAlphabet }
var isLowercaseAlphabet: Bool { "a"..."z" ~= self }
var isUppercaseAlphabet: Bool { "A"..."Z" ~= self }
func rotateAlphabetLetter(_ factor: Int) -> Self? {
precondition(factor > 0, "rotation must be positive")
guard let asciiValue = asciiValue, isAlphabet else { return nil }
let addition = asciiValue + UInt8(factor % 26)
return .init(UnicodeScalar(addition > (isLowercaseAlphabet ? 122 : 90) ? addition - 26 : addition))
}
}
Character("a").rotateAlphabetLetter(2) // "c"
Character("A").rotateAlphabetLetter(2) // "C"
Character("j").rotateAlphabetLetter(2) // "l"
Character("J").rotateAlphabetLetter(2) // "L"
Character("z").rotateAlphabetLetter(2) // "b"
Character("Z").rotateAlphabetLetter(2) // "B"
Character("ç").rotateAlphabetLetter(2) // nil
Character("Ç").rotateAlphabetLetter(2) // nil
Expanding on that you can map your string elements using compactMap:
let string = "XYZ"
let rotatedAlphabetLetters = string.compactMap { $0.rotateAlphabetLetter(2) } // ["Z", "A", "B"]
And to convert the sequence of characters back to string:
extension Sequence where Element == Character {
var string: String { .init(self) }
}
let result = rotatedAlphabetLetters.string // "ZAB"
or simply in one liner:
let result = "XYZ".compactMap { $0.rotateAlphabetLetter(2) }.string // "ZAB"
I am creating a hangman app and the if statement is not working when I remove it the code works, but only for one animal. The code should update the label, placing the letter you pressed in the appropriate place if the word contains that letter. I tried creating a switch
(random is the word that is selected from an array of animals)
switch random {
case "aardvark":
(the code for when random is aardvark)
default:
(the code for sea turtle) }
but the default case would execute every time, even when random was aardvark
#IBAction func aPressed(_ sender: Any) {
if random == "aardvark" {
if aardvark[0] == "a" {
aar[0] = "a"
};if aardvark[1] == "a" {
aar[1] = "a"
};if aardvark[2] == "a" {
aar[2] = "a"
};if aardvark[3] == "a" {
aar[3] = "a"
};if aardvark[4] == "a" {
aar[4] = "a"
};if aardvark[5] == "a" {
aar[5] = "a"
};if aardvark[6] == "a" {
aar[6] = "a"
};if aardvark[7] == "a" {
aar[7] = "a"
} else if aardvark[0] != "a" , aardvark[1] != "a" , aardvark[2] != "a" , aardvark[3] != "a" , aardvark[4] != "a" , aardvark[5] != "a" , aardvark[6] != "a" , aardvark[7] != "a" {
wrong += 1
}
theWord.text = self.aar.joined(separator: " ")
}
if random == "sea turtle" {
if seaTurtle[2] == "a" {
sTurt[2] = "a"
theWord.text = self.sTurt.joined(separator: " ")
}
}
buttonA.isHidden = true
updateImage()
}
Apart from the structural issues your code has, you have consider that you can't just hard-code the checking of every letter, one by one. Your code will need to loop (either explicitly by loops you write, or implicitly by using functions that loop for you) through the letters of the answer, comparing them with the guess, and modifying the game board appropriately. Here's an example:
let word = "Aardvark"
var gameBoard = "XXXXXXXX"
let guess: Character = "a"
let indicies = zip(word.lowercased(), word.indices).flatMap{ (pair: (letter: Character, index: String.Index)) in
return pair.letter == guess ? pair.index : nil
}
indicies.forEach{ gameBoard.replaceSubrange($0...$0, with: word[$0...$0]) }
print(gameBoard) //AaXXXaXX
I need to sort an array of JSON objects.
but it is needs to be translated from a literal meaning to a numeric meaning.
for example
object["status"]
"New" = 1
"Open" = 2
"Closed" = 3
/// I need to translated in here some where
var sortedOrders = orders.sort { $0["status"].doubleValue < $1["status"].doubleValue }
You could do this with an enum.
enum Status: Int {
case new = 1
case open = 2
case closed = 3
case unknown = 99
init(string: String) {
switch string {
case "new", "New": self = .new
case "open", "Open": self = .open
case "closed", "Closed": self = .closed
default:
self = .unknown
}
}
}
To use the enum, you could initialize like this:
var myStatus = Status(string: object["status"])
And use it like this:
print(myStatus) // prints "new"
print(myStatus.rawValue) // prints "1"
Edit: Since the enum has an underlying type of Int, to accomplish your sort you can compare the resulting Status directly (Thanks to this question https://stackoverflow.com/a/27871946/1718685):
var sortedOrders = orders.sort { Status(string: $0["status"]) < Status(string: $1["status"]) }
Here's one way:
let statuses = [ "New", "Open", "Closed" ]
var sortedOrders = orders.sort { (statuses.index(of: $0["status"] ?? "") ?? 99) < (statuses.index(of: $1["status"] ?? "") ?? 99) }
This will determine the index of each status within the statuses array. 99 will be used for unknown or missing statuses so any unknown statuses will appear at the end of the list.
I'm trying to implement a groupBy functionality where all the numbers of a nested list are grouped. My code so far:
struct MyClass {
var numbers: [Int]
...
}
var dict: [String : MyClass] = ...
let numbers = dict
.filter{ $0.0.containsString(searchString) }
.flatMap{ $0.1.numbers }
This yields me an Array of Ints. However I'd like to have a dictionary [Int : Int] with each unique number and the count of its occurence. So for example:
[1,2,3,4,1,2,2,1]
should be:
[1 : 2, 2 : 3, 3 : 1, 4 : 1]
I know there's a groupBy operator, but Swift doesn't seem to have one. I've tried with reduce:
func reducer(accumulator: [Int: Int], num: Int) -> [Int : Int] {
var acc = accumulator
acc[num]! += 1
return acc
}
filtered.reduce([:], combine: reducer)
But it crashes when I want to run it. Not sure why, I get a EXC_BAD_INSTRUCTION.
I'd appreciate any help.
let numbers = [1,2,3,4,1,2,2,1]
var results = [Int: Int]()
Set(numbers).forEach { number in results[number] = numbers.filter { $0 == number }.count }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
Actually I'm not very sure if this is what you want. I just looked at your examples.
Using NSCountedSet:
var objects = [1,2,3,4,1,2,2,1]
let uniques = NSCountedSet(array: objects)
uniques.forEach { results[$0 as! Int] = uniques.countForObject($0) }
print(results) // [2: 3, 3: 1, 1: 3, 4: 1]
I would expect the crash to be ocurring on this line:
acc[num]! += 1
The first time this is called for a number, the entry doesn't exist in the dictionary yet so acc[num] is nil. Forcefully unwrapping it would cause a crash.
Not sure if this is the best solution but you can simple check for this case:
if (acc[num]) {
acc[num]! += 1
} else {
acc[num] = 1
}
Cleaner code from #vacawama in the comments:
acc[num] = (acc[num] ?? 0) + 1
Here's an extension to Array that does what you're asking:
extension Array where Element: Hashable {
var grouped: [Element:Int] {
var dict = [Element:Int]()
self.forEach { dict[$0] = (dict[$0] ?? 0) + 1 }
return dict
}
}
The key is the closure: { dict[$0] = (dict[$0] ?? 0) + 1 }.
It takes the current value in the array, tests to see if it's a key in the dictionary, returns the value for that key if it exists or 0 if it doesn't, then adds one and sets the key:value to be the pair of the current value and occurrences so far.
Example use:
[1,2,3,4,1,2,2,1].grouped // => [2: 3, 3: 1, 1: 3, 4: 1]
You need something like this:
if let _ = acc.indexForKey(num) {
acc[num]! += 1
}
else {
acc[num] = 1
}
It's sort of unclear what you're asking for, but here's a function that will take an array of ints and return a dictionary with the number as the key, and the count as the value:
func getDictionaryOfCounts(accumulator: [Int]) -> [Int : Int] {
var countingDictionary: [Int : Int] = [:]
accumulator.forEach { (value) in
if countingDictionary[value] != nil {
countingDictionary[value]! += 1
}
else{
countingDictionary[value] = 1
}
}
return countingDictionary
}
Would like to add an additional text at the end of an existing text in an array-item. The code which I have till now looks like:
for var i = 0; i < arrMain.count; i++ {
if (arrMain[i] as NSString).containsString("#ID-001") {
println("OK")
// Add additional text (eg. "Test") at the end of #ID-001
}
}
Every tried combination overwrites me #ID-001...
Try:
var arrMain:[AnyObject] = ["#ID-001"]
for var i = 0; i < arrMain.count; i++ {
if (arrMain[i] as NSString).containsString("#ID-001") {
arrMain[i] = (arrMain[i] as String) + "Test"
}
}
Either do this with the for-loop you already have, e.g.
var x = [ "a", "b", "c" ]
for index in 0 ..< x.count
{
if x[index] == "b"
{
x[index] += "_hello"
}
}
or use Swift's map function:
let y = x.map({ value -> String in return value == "b" ? value + "_hello" : value })
Please note, that
The second example will make a copy of the array.
Your array needs to be a mutable array, e.g. let x = [ ... ] won't work.
Assuming I understand the question:
arrMain[i] = arrMain[i].stringByReplacingOccurrencesOfString("#ID-001", withString: "#ID-001Test")