The initialization of my playerCard does not work - ios

I'm new to swift and I'm trying to make a simple card game where the player and computer draws a card and whoever has the largest card wins. But when I call my compareCards function, I got an error: constant 'playerCard' used before being initialized. I thought I already initialized playerCard so I'm wondering if someone could tell me what's wrong with my code? Thank you.
import Foundation
func randomInteger(upper: Int) -> Int {
return Int(arc4random_uniform(UInt32(upper)))
}
enum Rank: Int{
case two = 2,
three,
four, five,
six,
seven,
eight,
nine,
ten,
jack,
queen,
king,
ace
static func allValues() -> [Rank]{
return [two, three, four, five, six, seven, eight, nine, ten, jack, queen, king, ace]
}
}
enum Suit: Int{
case clubs = 1,
diamonds,
hearts,
spades
static func allValues() -> [Suit]{
return [spades, hearts, diamonds, clubs]
}
}
struct Card{
var rank: Rank = .two
var suit: Suit = .clubs
init(rank: Rank, suit: Suit){
self.rank = rank
self.suit = suit
}
}
class Deck{
var deck: [Card] = []
var rankArray: [Rank] = []
var suitArray: [Suit] = []
init(){
rankArray = Rank.allValues()
suitArray = Suit.allValues()
for aRank in rankArray{
for aSuit in suitArray{
let aCard = Card(rank: aRank, suit: aSuit)
deck.append(aCard)
}
}
}
func drawOne() -> Card?{
if deck.count != 0{
let randomCard = randomInteger(upper: deck.count)
let aCard = deck[randomCard]
deck.remove(at: randomCard)
return aCard
}
else{
return nil
}
}
}
func compareCards(playerCard: Card, computerCard: Card) -> String{
var isPlayerGreater: Bool = false
if playerCard.rank != computerCard.rank{
if playerCard.rank.rawValue > computerCard.rank.rawValue{
isPlayerGreater = true
}
}
if playerCard.suit.rawValue > computerCard.suit.rawValue{
isPlayerGreater = true
}
if isPlayerGreater == true{
return "The player won with the \(playerCard.rank) of \(playerCard.suit)!"
}
else{
return "The computer won with the \(computerCard.rank) of \(computerCard.suit)!"
}
}
/////////////////////////////////////////////////////////////////////////////////////////////////
let playerCard: Card
let computerCard: Card
let aDeck = Deck()
if let aCard = aDeck.drawOne(){
playerCard = Card(rank: aCard.rank, suit: aCard.suit)
}
if let aCard = aDeck.drawOne(){
computerCard = Card(rank: aCard.rank, suit: aCard.suit)
}
var result: String = compareCards(playerCard: playerCard, computerCard: computerCard)
print(result)

because you didn't initialize. your darawOne() function is nullable and you set condition " if aDeck -> playercard = aDeck". what about if result == nil???
I change your last code to this:
let aDeck = Deck()
if let aCard = aDeck.drawOne(), let seCard = aDeck.drawOne(){
let playerCard = Card(rank: aCard.rank, suit: aCard.suit)
let computerCard = Card(rank: aCard.rank, suit: seCard.suit)
let result: String = compareCards(playerCard: playerCard, computerCard: computerCard)
print(result)
}

Below code works well.
let aDeck = Deck()
if let playerCard = aDeck.drawOne(), let computerCard = aDeck.drawOne() {
var result: String = compareCards(playerCard: playerCard, computerCard: computerCard)
print(result)
}
Error was thrown by compiler because you have declared two non-optional constants but not initialised it.

Your problem is that you must init playerCard and computerCard before using it. If your code will not pass if let statement your cards will not init.
Here you have two options atleast either provide a default value to your variables either mark them as force unwrapped so the compiler will ignore not inited state as you telling that you 100% sure variables will be at run time.
The second option will look next:
Replace your
let playerCard: Card
let computerCard: Card
With:
var playerCard: Card!
var computerCard: Card!

You need to just declare playerCard and computerCard variable with var keyword instead of let
You can use let when you know that once you assign a value to a variable, it doesn't change and with using var you can change the value to a variable.
var playerCard: Card
var computerCard: Card
let aDeck = Deck()
if let aCard = aDeck.drawOne(){
playerCard = Card(rank: aCard.rank, suit: aCard.suit) //you are assigning/changing the value here of playerCard variable.
}
if let aCard = aDeck.drawOne(){
computerCard = Card(rank: aCard.rank, suit: aCard.suit) //you are assigning/changing the value here of playerCard variable.
}

Related

Adding Double and a String to then display on a UILabel

I am trying to add up a value that is entered in the text field with a value specified as a double and then returning the value on a label. The code that I have is :
#IBOutlet weak var enterField: UITextField!
var weekOneTotal:Double = 0
#IBAction func addButton(_ sender: Any) {
addCorrectValue()
}
func addCorrectValue () {
guard let addAmount = convertAmount(input: enterField.text!) else {
print("Invalid amount")
return
}
let newValue = weekOneTotal += addAmount
secondScreen.weekOneAmountLabel.text = String(newValue)
}
func convertAmount (input:String) -> Double? {
let numberFormatter = NumberFormatter ()
numberFormatter.numberStyle = .decimal
return numberFormatter.number(from: input)?.doubleValue
}
Try this:
func addCorrectValue () {
guard let addAmount = Double(enterField.text!) else {
print("Invalid amount")
return
}
let newValue = weekOneTotal + addAmount
secondScreen.weekOneAmountLabel.text = "\(String(format: "%.1f", newValue))"
}
The .1 is the number of decimals that are shown. You can adjust that to your needs. Hope I understood the question and this works for you!
You probably want to increase value of weekOneTotal variable by converted amount and then you want to use this value as text of some label
weekOneTotal += addAmount
secondScreen.weekOneAmountLabel.text = String(weekOneTotal)

add the values according to appending the values

How to add the values according to appending the values in swift3.
this is my datasource:-
class QM_ChartDataSourceModel: NSObject {
var dataListArray:Array<QM_CartModel>? = []
init(array :Array<[String:Any]>?) {
super.init()
var newArray:Array<[String:Any]> = []
if array == nil{
newArray = self.getJsonDataStored22()
}
else{
newArray = array!
}
var datalist:Array<QM_CartModel> = []
for dict in newArray{
let model = QM_CartModel(dictionary: dict)
datalist.append(model!)
}
self.dataListArray = datalist
}
}
typealias dummyDataSource22 = QM_ChartDataSourceModel
extension dummyDataSource22{
func getJsonDataStored22() ->Array<Dictionary<String,String>>{
let jsonArray = [["id":"311","name":"Dosa Fest","price":"QR 40","quantity":"3"],["id":"312","name":"Organic Vegan Fest","price":"QR 40","quantity":"2"],["id":"313","name":"Food Of Life Time","price":"QR 56","quantity":"7"],["id":"314","name":"Tea Time","price":"QR 88","quantity":"1"],["id":"315","name":"Dosa Fest","price":"QR 13","quantity":"6"],["id":"316","name":"Organic Vegan Fest","price":"QR 4","quantity":"8"],["id":"317","name":"Food Of Life Time","price":"QR 90","quantity":"3"],["id":"318","name":"Tea Time","price":"QR 66","quantity":"2"],["id":"319","name":"Dosa Fest","price":"QR 81","quantity":"6"],["id":"320","name":"Organic Vegan Fest","price":"QR 49","quantity":"2"]] as Array<Dictionary<String,String>>
return jsonArray
}
}
in tableviewcell:
func setEventData(carts:QM_CartModel)
{
self.name.text = carts.cartname
self.price.text = carts.cartsum
self.itemQuantityStepper.value = 1
setItemQuantity(quantity)
print(self.price.text)
let value = carts.cartsum
let x: Int? = Int(value!)
print(x)
let add = x!
print(add)
let theIntegerValue1 :Int = add
let theStringValue1 :String = String(theIntegerValue1)
self.price.text = theStringValue1
}
my model:-
class QM_CartModel: NSObject {
var cartname :String!
var cartprice:String!
var cartquantity:String!
var carttotalprice:String!
var carttotal:String!
var cartQR:String!
var cartvalue:String!
var cartsum:String?
var cartid:String!
init?(dictionary :JSONDictionary) {
guard let name = dictionary["name"] as? String else {
return
}
if let quantity = dictionary["quantity"] as? String{
let price = dictionary["price"] as? String
let id = dictionary["id"] as? String
self.cartid = id
self.cartprice = price
self.cartquantity = quantity
let fullNameArr = price?.components(separatedBy: " ")
let QR = fullNameArr?[0]
let value = fullNameArr?[1]
self.cartQR = QR
self.cartvalue = value
let x: Int? = Int(value!)
print(x)
let y:Int? = Int(quantity)
print(y)
let sum = x! * y!
print(sum)
let sum1 = String(describing: sum)
cartsum = sum1
}
my viewmodel:-
class QM_ChartViewModel: NSObject {
var datasourceModel:QM_ChartDataSourceModel
var insertedArray:QM_CartModel?
var filteredListArray:Array<QM_CartModel>? = []
var totalListArray:Array<QM_CartModel>? = []
init(withdatasource newDatasourceModel: QM_ChartDataSourceModel) {
datasourceModel = newDatasourceModel
print(datasourceModel.dataListArray)
}
func datafordisplay(atindex indexPath: IndexPath) -> QM_CartModel{
return datasourceModel.dataListArray![indexPath.row]
}
func numberOfRowsInSection(section:Int) -> Int {
return datasourceModel.dataListArray!.count
}
func delete(atIndex indexPath: IndexPath) {
datasourceModel.dataListArray!.remove(at: indexPath.row)
}
func search(idsearch :String?) {
filteredListArray = datasourceModel.dataListArray?.filter{($0.cartid?.range(of: idsearch!, options: .caseInsensitive) != nil)}
print(filteredListArray)
}
func searchindex(objectatindex index: Int) -> QM_CartModel {
return self.filteredListArray![index]
}
func total()
{ totalListArray = datasourceModel.dataListArray?.filter{($0.cartsum != nil)}
print(totalListArray)
}
func add(){
datasourceModel.dataListArray?.append(insertedArray!)
print(datasourceModel.dataListArray)
print(insertedArray?.offerAddName)
print(insertedArray?.offerprice)
self.datasourceModel.dataListArray = datasourceModel.dataListArray
print(insertedArray?.cartsum)
}
func addquantity(quantity:Int)
{
// datasourceModel.dataListArray?.filter{ $0.cartid! == cartaddedid! }.first?.qty = quantity as NSNumber?
}
}
in viewcontroller my code as below:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return chartViewModel.numberOfRowsInSection(section: section)
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let identifier = "cell"
var cell: QM_ChartCell! = tableView.dequeueReusableCell(withIdentifier: identifier) as? QM_ChartCell
if cell == nil {
tableView.register(UINib(nibName: "QM_ChartCell", bundle: nil), forCellReuseIdentifier: identifier)
cell = tableView.dequeueReusableCell(withIdentifier: identifier) as? QM_ChartCell
}
cell.setEventData(carts: chartViewModel.datafordisplay(atindex: indexPath))
print(cell.numbers)
see here can see the total.So that way i need to display the total
this is my code ...here i getting the values model.cartsum.So this value is appending in var number:[String] = []
.But here i need-as values are appending ,here i need to add the number.So first value is 1 and second value is 2 then i need to add this values.And if next number is 3 then i need to get sum = 6.
How to get
You need to calculate all the cart stuff just after you get it either from service or from local. You don't need to do calculation in cellForRowAtIndex: method because it should be done once.
I assume this is your data structure as mentioned in question.
let jsonArray = [["id":"311","name":"Dosa Fest","price":"QR 40","quantity":"3"],
["id":"312","name":"Organic Vegan Fest","price":"QR 40","quantity":"2"],
["id":"313","name":"Food Of Life Time","price":"QR 56","quantity":"7"],
["id":"314","name":"Tea Time","price":"QR 88","quantity":"1"],
["id":"315","name":"Dosa Fest","price":"QR 13","quantity":"6"],
["id":"316","name":"Organic Vegan Fest","price":"QR 4","quantity":"8"],
["id":"317","name":"Food Of Life Time","price":"QR 90","quantity":"3"],
["id":"318","name":"Tea Time","price":"QR 66","quantity":"2"],
["id":"319","name":"Dosa Fest","price":"QR 81","quantity":"6"],
["id":"320","name":"Organic Vegan Fest","price":"QR 49","quantity":"2"]]
Here is how to calculate the total of the cart. As per your data considering price is in Int
var total = 0
for item in jsonArray {
/// Will check if quantity is available in dictionary and convertible into an Int else will be 0
let quantity = Int(item["quantity"] ?? "0") ?? 0
/// Will check price key exists in the dictionary
if let priceStr = item["price"] {
/// Will fetch the last components and check if it is convertible into an Int else 0
let price = Int(priceStr.components(separatedBy: " ").last ?? "0") ?? 0
/// Multiply price with quantity and add into total
total += price * quantity
}
}
print(total)
Output: 1776
Another way:
let total = jsonArray.map { (item) -> Int in
let quantity = Int(item["quantity"] ?? "0") ?? 0
let price = Int(item["price"]?.components(separatedBy: " ").last ?? "0") ?? 0
return quantity * price
}.reduce(0, +)
print(total)
Please try this code if you have array of Int
var arrayOfInt = [2,3,4,5,4,7,2]
let reducedNumberSum = arrayOfInt.reduce(0,+)
print(reducedNumberSum)
Answer: 27
In your code
let model = chartViewModel.datafordisplay(atindex: indexPath)
Please describe more so we can answer according your problem.

IOS Swift 2.0 Card shuffling function [duplicate]

This question already has answers here:
How do I shuffle an array in Swift?
(25 answers)
Closed 6 years ago.
Noob here, I am trying to create a card game using a standard deck of 52 cards. Here is the code I would like to make into a func so I dont have to manually write it out every single time. I am creating 5 different players so this would be replicated to other players.
func firstPlayerCardShuffle() {
var firstPlayerCard1Num = (Int(arc4random_uniform(UInt32(13)) + 2))
var firstPlayerCard1Suit = suits[Int(arc4random_uniform(UInt32(suits.count)))]
var firstPlayerCard1 = "\(firstPlayerCard1Num) of \(firstPlayerCard1Suit)"
var firstPlayerCard2Num = (Int(arc4random_uniform(UInt32(13)) + 2))
var firstPlayerCard2Suit = suits[Int(arc4random_uniform(UInt32(suits.count)))]
var firstPlayerCard2 = "\(firstPlayerCard2Num) of \(firstPlayerCard2Suit)"
return(firstPlayerCard1,firstPlayerCard2)
}
Can someone let me know what I'm missing.
Not a direct answer to your question, but I think you'll want something like this:
enum Number: String {
case Two = "two"
case Three = "three"
case Four = "four"
case Five = "five"
case Six = "six"
case Seven = "seven"
case Eight = "eight"
case Nine = "nine"
case Ten = "ten"
case Jack = "jack"
case Queen = "queen"
case King = "king"
case Ace = "ace"
static var randomNumber: Number {
return [Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace][Int(arc4random_uniform(13))]
}
}
enum Suit: String {
case Spades = "spades"
case Hearts = "hearts"
case Diamonds = "diamonds"
case Clubs = "clubs"
static var randomSuit: Suit {
return [Spades, Hearts, Diamonds, Clubs][Int(arc4random_uniform(4))]
}
}
struct Card: CustomStringConvertible, Equatable {
let number: Number
let suit: Suit
var description: String {
return "\(number.rawValue) of \(suit.rawValue)"
}
static var randomCard: Card {
return Card(number: Number.randomNumber, suit: Suit.randomSuit)
}
static func randomCards(count count: Int) -> [Card] {
guard count > 0 else {
return []
}
guard count <= 52 else {
fatalError("There only are 52 unique cards.")
}
let cards = randomCards(count: count - 1)
while true {
let card = randomCard
if !cards.contains(card) {
return cards + [card]
}
}
}
}
func == (left: Card, right: Card) -> Bool {
return left.number == right.number && left.suit == right.suit
}
let randomCards = Card.randomCards(count: 5)
print(randomCards)
// prints five random cards
Let me know if you have any other questions.

Swift Anagram checker

I am attempting to build an anagram checker for swift. This is my code. In case you don't know an anagram checker checks if two strings have the same characters in them but, order does not matter.
func checkForAnagram(#firstString: String, #secondString: String) -> Bool {
var firstStringArray: [Character] = []
var secondStringArray: [Character] = []
/* if case matters delete the next four lines
and make sure your variables are not constants */
var first = firstString
var second = secondString
first = first.lowercaseString
second = second.lowercaseString
for charactersOne in first {
firstStringArray += [charactersOne]
}
for charactersTwo in second {
secondStringArray += [charactersTwo]
}
if firstStringArray.count != secondStringArray.count {
return false
} else {
for elements in firstStringArray {
if secondStringArray.contains(elements){
return true
} else {
return false
}
}
}
}
var a = "Hello"
var b = "oellh"
var c = "World"
checkForAnagram(firstString: a, secondString: b)
I am getting an error message of.
'[Character]' does not have a member 'contains'
The accepted answer is compact and elegant, but very inefficient if compared to other solutions.
I'll now propose and discuss the implementation of a few variants of anagram checker. To measure performance, I'll use the different variants to find the anagrams of a given word out of an array of 50,000+ words.
// Variant 1: Sorting of Character
// Measured time: 30.46 s
func anagramCheck1(a: String, b: String) -> Bool {
return a.characters.sorted() == b.characters.sorted()
}
This is essentially the solution of the accepted answer, written in Swift 3 syntax. It's very slow because Swift's String, unlike NSString, is based on Character, which handles Unicode characters properly.
A more efficient solution exploits the NSCountedSet class, which allows us to represent a string as a set of characters, each with its own count. Two strings are anagrams if they map to the same NSCountedSet.
Note: checking string lengths as a precondition makes the implementation always more efficient.
// Variant 2: NSCountedSet of Character
// Measured time: 4.81 s
func anagramCheck2(a: String, b: String) -> Bool {
guard a.characters.count == b.characters.count else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for c in a.characters {
aSet.add(c)
}
for c in b.characters {
bSet.add(c)
}
return aSet == bSet
}
Better but not excellent. Here, one of the "culprits" is the use of the native Swift Character type (from Swift's String). Moving back to good old Objective-C types (NSString and unichar) makes things more efficient.
// Variant 3: NSCountedSet of unichar
// Measured time: 1.31 s
func anagramCheck3(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for i in 0..<length {
aSet.add(aString.character(at: i))
bSet.add(bString.character(at: i))
}
return aSet == bSet
}
Using NSCountedSet is fine, but before we compare two NSCountedSet objects, we fully populate them. A useful alternative is to fully populate the NSCountedSet for only one of the two strings, and then, while we populate the NSCountedSet for the other string, we fail early if the other string contains a character that is not found in the NSCountedSet of the first string.
// Variant 4: NSCountedSet of unichar and early exit
// Measured time: 1.07 s
func anagramCheck4(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
let aSet = NSCountedSet()
let bSet = NSCountedSet()
for i in 0..<length {
aSet.add(aString.character(at: i))
}
for i in 0..<length {
let c = bString.character(at: i)
if bSet.count(for: c) >= aSet.count(for: c) {
return false
}
bSet.add(c)
}
return true
}
This is about the best timing we are going to get (with Swift). However, for completeness, let me discuss one more variant of this kind.
The next alternative exploits a Swift Dictionary of type [unichar: Int] to store the number of repetitions for each character instead of NSCountedSet. It's slightly slower than the previous two variants, but we can reuse it later to obtain a faster implementation.
// Variant 5: counting repetitions with [unichar:Int]
// Measured time: 1.36
func anagramCheck5(a: String, b: String) -> Bool {
let aString = a as NSString
let bString = b as NSString
let length = aString.length
guard length == bString.length else { return false }
var aDic = [unichar:Int]()
var bDic = [unichar:Int]()
for i in 0..<length {
let c = aString.character(at: i)
aDic[c] = (aDic[c] ?? 0) + 1
}
for i in 0..<length {
let c = bString.character(at: i)
let count = (bDic[c] ?? 0) + 1
if count > aDic[c] ?? 0 {
return false
}
bDic[c] = count
}
return true
}
Note that a vanilla Objective-C implementation using NSCountedSet, corresponding to Variant 3, is faster than all the previous versions by a rather large margin.
// Variant 6: Objective-C and NSCountedSet
// Measured time: 0.65 s
- (BOOL)anagramChecker:(NSString *)a with:(NSString *)b {
if (a.length != b.length) {
return NO;
}
NSCountedSet *aSet = [[NSCountedSet alloc] init];
NSCountedSet *bSet = [[NSCountedSet alloc] init];
for (int i = 0; i < a.length; i++) {
[aSet addObject:#([a characterAtIndex:i])];
[bSet addObject:#([b characterAtIndex:i])];
}
return [aSet isEqual:bSet];
}
Another way we can improve upon the previous attempts is to observe that, if we need to find the anagram of a given word, we might as well consider that word as fixed, and thus we could build the corresponding structure (NSCountedSet, Dictionary, ...) for that word only once.
// Finding all the anagrams of word in words
// Variant 7: counting repetitions with [unichar:Int]
// Measured time: 0.58 s
func anagrams(word: String, from words: [String]) -> [String] {
let anagrammedWord = word as NSString
let length = anagrammedWord.length
var aDic = [unichar:Int]()
for i in 0..<length {
let c = anagrammedWord.character(at: i)
aDic[c] = (aDic[c] ?? 0) + 1
}
let foundWords = words.filter {
let string = $0 as NSString
guard length == string.length else { return false }
var bDic = [unichar:Int]()
for i in 0..<length {
let c = string.character(at: i)
let count = (bDic[c] ?? 0) + 1
if count > aDic[c] ?? 0 {
return false
}
bDic[c] = count
}
return true
}
return foundWords
}
Now, in the previous variant we have counted with a [unichar:Int] Dictionary. This proves slightly more efficient than using an NSCountedSet of unichar, either with early exit (0.60 s) or without (0.87 s).
You should try
func checkForAnagram(firstString firstString: String, secondString: String) -> Bool {
return firstString.lowercaseString.characters.sort() == secondString.lowercaseString.characters.sort()
}
func checkAnagrams(str1: String, str2: String) -> Bool {
guard str1.count == str2.count else { return false }
var dictionary = Dictionary<Character, Int>()
for index in 0..<str1.count {
let value1 = str1[str1.index(str1.startIndex, offsetBy: index)]
let value2 = str2[str2.index(str2.startIndex, offsetBy: index)]
dictionary[value1] = (dictionary[value1] ?? 0) + 1
dictionary[value2] = (dictionary[value2] ?? 0) - 1
}
return !dictionary.contains(where: {(_, value) in
return value != 0
})
}
Time complexity - O(n)
// Make sure name your variables correctly so you won't confuse
// Mutate the constants parameter, lowercase to handle capital letters and the sorted them to compare both. Finally check is there are equal return true or false.
func anagram(str1: String, srt2: String)->Bool{
let string1 = str1.lowercased().sorted()
let string2 = srt2.lowercased().sorted()
if string1 == string2 {
return true
}
return false
}
// This answer also would work
// Convert your parameters on Array, then sorted them and compare them
func ana(str1: String, str2: String)->Bool{
let a = Array(str1)
let b = Array(str2)
if a.sorted() == b.sorted() {
return true
}
return false
}
Don't forget whitespaces
func isAnagram(_ stringOne: String, stringTwo: String) -> Bool {
return stringOne.lowercased().sorted().filter { $0 != " "} stringTwo.lowercased().sorted().filter { $0 != " "}
}
Swift 4.1 Function will give you 3 questions answer for Anagram :-
1. Input Strings (a,b) are Anagram ? //Bool
2. If not an Anagram then number of count require to change Characters in strings(a,b) to make them anagram ? // Int
3. If not an Anagram then list of Characters needs to be change in strings(a,b) to make them anagram ? // [Character]
STEP 1:- Copy and Paste below function in to your required class:-
//MARK:- Anagram checker
func anagramChecker(a:String,b:String) -> (Bool,Int,[Character]) {
var aCharacters = Array(a)
var bCharacters = Array(b)
var count = 0
var isAnagram = true
var replacementRequiredWords:[Character] = [Character]()
if aCharacters.count == bCharacters.count {
let listA = aCharacters.filter { !bCharacters.contains($0) }
for i in 0 ..< listA.count {
if !replacementRequiredWords.contains(listA[i]) {
count = count + 1
replacementRequiredWords.append(listA[i])
isAnagram = false
}
}
let listB = bCharacters.filter { !aCharacters.contains($0) }
for i in 0 ..< listB.count {
if !replacementRequiredWords.contains(listB[i]) {
count = count + 1
replacementRequiredWords.append(listB[i])
isAnagram = false
}
}
}else{
//cant be an anagram
count = -1
}
return (isAnagram,count,replacementRequiredWords)
}
STEP 2 :- Make two Input Strings for test
// Input Strings
var a = "aeb"
var b = "abs"
STEP 3:- Print results :-
print("isAnagram : \(isAnagram(a: a, b: b).0)")
print("number of count require to change strings in anagram : \(isAnagram(a: a, b: b).1)")//-1 will come in case of cant be a Anagram
print("list of Characters needs to be change : \(isAnagram(a: a, b: b).2)")
Results of above exercise:-
isAnagram : false
number of count require to change strings in anagram : 2
list of Characters needs to be change : ["e", "s"]
Hope this 10 minutes exercise will give some support to my Swift
family for solving Anagram related problems easily. :)
We can use dictionary to construct a new data structure container. Then compare the value by key/character of the string.
func anagram(str1: String, str2 : String) -> Bool {
var dict1 = [Character: Int]()
var dict2 = [Character:Int]()
for i in str1 {
if let count = dict1[i] {
dict1[i] = count + 1
} else {
dict1[i] = 1
}
}
for j in str2 {
if let count = dict2[j] {
dict2[j] = count + 1
} else {
dict2[j] = 1
}
}
return dict1 == dict2 ? true : false
}
// input -> "anna", "aann"
// The count will look like:
// ["a": 2, "n": 2] & ["a": 2, "n": 2]
// then return true
Another easy that I just realise doing an Anagram function in Swift 5.X
func checkForAnagram(firstString firstString: String, secondString: String) -> Bool {
return !firstString.isEmpty && firstString.sorted() == secondString.sorted()
}
class Solution {
func isAnagram(_ s: String, _ t: String) -> Bool {
guard s.count == t.count else { return false }
let dictS = s.reduce(into: [Character: Int]()) { $0[$1, default: 0] += 1 }
let dictT = t.reduce(into: [Character: Int]()) { $0[$1, default: 0] += 1 }
for letter in s {
if let count = dictS[letter] {
guard count == dictT[letter] else { return false }
}
}
return true
}
}
Check two strings are anagram using inout method in Swift
func checkAnagramString(str1: inout String, str2: inout String)-> Bool{
var result:Bool = false
str1 = str1.lowercased().trimmingCharacters(in: .whitespace)
str2 = str2.lowercased().trimmingCharacters(in: .whitespaces)
if (str1.count != str2.count) {
return result
}
for c in str1 {
if str2.contains(c){
result = true
}
else{
result = false
return result
}
}
return result
}
Call function to check strings are anagram or not
var str1 = "tommarvoloriddle"
var str2 = "iamlordvoldemort"
print(checkAnagramString(str1: &str1, str2: &str2)) //Output = true.
func isAnagram(word1: String, word2: String) -> Bool {
let set1 = Set(word1)
let set2 = Set(word2)
return set1 == set2
}
or
func isAnagram(word1: String,word2: String) -> Bool {
return word1.lowercased().sorted() == word2.lowercased().sorted()
}

Converting String to Int with Swift

The application basically calculates acceleration by inputting Initial and final velocity and time and then use a formula to calculate acceleration. However, since the values in the text boxes are string, I am unable to convert them to integers.
#IBOutlet var txtBox1 : UITextField
#IBOutlet var txtBox2 : UITextField
#IBOutlet var txtBox3 : UITextField
#IBOutlet var lblAnswer : UILabel
#IBAction func btn1(sender : AnyObject) {
let answer1 = "The acceleration is"
var answer2 = txtBox1
var answer3 = txtBox2
var answer4 = txtBox3
Updated answer for Swift 2.0+:
toInt() method gives an error, as it was removed from String in Swift 2.x. Instead, the Int type now has an initializer that accepts a String:
let a: Int? = Int(firstTextField.text)
let b: Int? = Int(secondTextField.text)
Basic Idea, note that this only works in Swift 1.x (check out ParaSara's answer to see how it works in Swift 2.x):
// toInt returns optional that's why we used a:Int?
let a:Int? = firstText.text.toInt() // firstText is UITextField
let b:Int? = secondText.text.toInt() // secondText is UITextField
// check a and b before unwrapping using !
if a && b {
var ans = a! + b!
answerLabel.text = "Answer is \(ans)" // answerLabel ie UILabel
} else {
answerLabel.text = "Input values are not numeric"
}
Update for Swift 4
...
let a:Int? = Int(firstText.text) // firstText is UITextField
let b:Int? = Int(secondText.text) // secondText is UITextField
...
myString.toInt() - convert the string value into int .
Swift 3.x
If you have an integer hiding inside a string, you can convertby using the integer's constructor, like this:
let myInt = Int(textField.text)
As with other data types (Float and Double) you can also convert by using NSString:
let myString = "556"
let myInt = (myString as NSString).integerValue
You can use NSNumberFormatter().numberFromString(yourNumberString). It's great because it returns an an optional that you can then test with if let to determine if the conversion was successful.
eg.
var myString = "\(10)"
if let myNumber = NSNumberFormatter().numberFromString(myString) {
var myInt = myNumber.integerValue
// do what you need to do with myInt
} else {
// what ever error code you need to write
}
Swift 5
var myString = "\(10)"
if let myNumber = NumberFormatter().number(from: myString) {
var myInt = myNumber.intValue
// do what you need to do with myInt
} else {
// what ever error code you need to write
}
edit/update: Xcode 11.4 • Swift 5.2
Please check the comments through the code
IntegerField.swift file contents:
import UIKit
class IntegerField: UITextField {
// returns the textfield contents, removes non digit characters and converts the result to an integer value
var value: Int { string.digits.integer ?? 0 }
var maxValue: Int = 999_999_999
private var lastValue: Int = 0
override func willMove(toSuperview newSuperview: UIView?) {
// adds a target to the textfield to monitor when the text changes
addTarget(self, action: #selector(editingChanged), for: .editingChanged)
// sets the keyboard type to digits only
keyboardType = .numberPad
// set the text alignment to right
textAlignment = .right
// sends an editingChanged action to force the textfield to be updated
sendActions(for: .editingChanged)
}
// deletes the last digit of the text field
override func deleteBackward() {
// note that the field text property default value is an empty string so force unwrap its value is safe
// note also that collection remove at requires a non empty collection which is true as well in this case so no need to check if the collection is not empty.
text!.remove(at: text!.index(before: text!.endIndex))
// sends an editingChanged action to force the textfield to be updated
sendActions(for: .editingChanged)
}
#objc func editingChanged() {
guard value <= maxValue else {
text = Formatter.decimal.string(for: lastValue)
return
}
// This will format the textfield respecting the user device locale and settings
text = Formatter.decimal.string(for: value)
print("Value:", value)
lastValue = value
}
}
You would need to add those extensions to your project as well:
Extensions UITextField.swift file contents:
import UIKit
extension UITextField {
var string: String { text ?? "" }
}
Extensions Formatter.swift file contents:
import Foundation
extension Formatter {
static let decimal = NumberFormatter(numberStyle: .decimal)
}
Extensions NumberFormatter.swift file contents:
import Foundation
extension NumberFormatter {
convenience init(numberStyle: Style) {
self.init()
self.numberStyle = numberStyle
}
}
Extensions StringProtocol.swift file contents:
extension StringProtocol where Self: RangeReplaceableCollection {
var digits: Self { filter(\.isWholeNumber) }
var integer: Int? { Int(self) }
}
Sample project
swift 4.0
let stringNumber = "123"
let number = Int(stringNumber) //here number is of type "Int?"
//using Forced Unwrapping
if number != nil {
//string is converted to Int
}
you could also use Optional Binding other than forced binding.
eg:
if let number = Int(stringNumber) {
// number is of type Int
}
In Swift 4.2 and Xcode 10.1
let string = "789"
if let intValue = Int(string) {
print(intValue)
}
let integerValue = 789
let stringValue = String(integerValue)
OR
let stringValue = "\(integerValue)"
print(stringValue)
//Xcode 8.1 and swift 3.0
We can also handle it by Optional Binding, Simply
let occur = "10"
if let occ = Int(occur) {
print("By optional binding :", occ*2) // 20
}
Swift 3
The simplest and more secure way is:
#IBOutlet var textFieldA : UITextField
#IBOutlet var textFieldB : UITextField
#IBOutlet var answerLabel : UILabel
#IBAction func calculate(sender : AnyObject) {
if let intValueA = Int(textFieldA),
let intValueB = Int(textFieldB) {
let result = intValueA + intValueB
answerLabel.text = "The acceleration is \(result)"
}
else {
answerLabel.text = "The value \(intValueA) and/or \(intValueB) are not a valid integer value"
}
}
Avoid invalid values setting keyboard type to number pad:
textFieldA.keyboardType = .numberPad
textFieldB.keyboardType = .numberPad
In Swift 4:
extension String {
var numberValue:NSNumber? {
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
return formatter.number(from: self)
}
}
let someFloat = "12".numberValue
Useful for String to Int and other type
extension String {
//Converts String to Int
public func toInt() -> Int? {
if let num = NumberFormatter().number(from: self) {
return num.intValue
} else {
return nil
}
}
//Converts String to Double
public func toDouble() -> Double? {
if let num = NumberFormatter().number(from: self) {
return num.doubleValue
} else {
return nil
}
}
/// EZSE: Converts String to Float
public func toFloat() -> Float? {
if let num = NumberFormatter().number(from: self) {
return num.floatValue
} else {
return nil
}
}
//Converts String to Bool
public func toBool() -> Bool? {
return (self as NSString).boolValue
}
}
Use it like :
"123".toInt() // 123
i have made a simple program, where you have 2 txt field you take input form the user and add them to make it simpler to understand please find the code below.
#IBOutlet weak var result: UILabel!
#IBOutlet weak var one: UITextField!
#IBOutlet weak var two: UITextField!
#IBAction func add(sender: AnyObject) {
let count = Int(one.text!)
let cal = Int(two.text!)
let sum = count! + cal!
result.text = "Sum is \(sum)"
}
hope this helps.
Swift 3.0
Try this, you don't need to check for any condition I have done everything just use this function. Send anything string, number, float, double ,etc,. you get a number as a value or 0 if it is unable to convert your value
Function:
func getNumber(number: Any?) -> NSNumber {
guard let statusNumber:NSNumber = number as? NSNumber else
{
guard let statString:String = number as? String else
{
return 0
}
if let myInteger = Int(statString)
{
return NSNumber(value:myInteger)
}
else{
return 0
}
}
return statusNumber
}
Usage:
Add the above function in code and to convert use
let myNumber = getNumber(number: myString)
if the myString has a number or string it returns the number else it returns 0
Example 1:
let number:String = "9834"
print("printing number \(getNumber(number: number))")
Output: printing number 9834
Example 2:
let number:Double = 9834
print("printing number \(getNumber(number: number))")
Output: printing number 9834
Example 3:
let number = 9834
print("printing number \(getNumber(number: number))")
Output: printing number 9834
About int() and Swift 2.x: if you get a nil value after conversion check if you try to convert a string with a big number (for example: 1073741824), in this case try:
let bytesInternet : Int64 = Int64(bytesInternetString)!
Latest swift3 this code is simply to convert string to int
let myString = "556"
let myInt = Int(myString)
Because a string might contain non-numerical characters you should use a guard to protect the operation. Example:
guard let labelInt:Int = Int(labelString) else {
return
}
useLabelInt()
I recently got the same issue. Below solution is work for me:
let strValue = "123"
let result = (strValue as NSString).integerValue
Swift5 float or int string to int:
extension String {
func convertStringToInt() -> Int {
return Int(Double(self) ?? 0.0)
}
}
let doubleStr = "4.2"
// print 4
print(doubleStr.convertStringToInt())
let intStr = "4"
// print 4
print(intStr.convertStringToInt())
Use this:
// get the values from text boxes
let a:Double = firstText.text.bridgeToObjectiveC().doubleValue
let b:Double = secondText.text.bridgeToObjectiveC().doubleValue
// we checking against 0.0, because above function return 0.0 if it gets failed to convert
if (a != 0.0) && (b != 0.0) {
var ans = a + b
answerLabel.text = "Answer is \(ans)"
} else {
answerLabel.text = "Input values are not numberic"
}
OR
Make your UITextField KeyboardType as DecimalTab from your XIB or storyboard, and remove any if condition for doing any calculation, ie.
var ans = a + b
answerLabel.text = "Answer is \(ans)"
Because keyboard type is DecimalPad there is no chance to enter other 0-9 or .
Hope this help !!
// To convert user input (i.e string) to int for calculation.I did this , and it works.
let num:Int? = Int(firstTextField.text!);
let sum:Int = num!-2
print(sum);
This works for me
var a:Int? = Int(userInput.text!)
for Swift3.x
extension String {
func toInt(defaultValue: Int) -> Int {
if let n = Int(self.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)) {
return n
} else {
return defaultValue
}
}
}
Swift 4, Swift 5
There are different cases to convert from something to something data type, it depends the input.
If the input data type is Any, we have to use as before convert to actual data type, then convert to data type what we want. For example:
func justGetDummyString() -> Any {
return "2000"
}
let dummyString: String = (justGetDummyString() as? String) ?? "" // output = "2000"
let dummyInt: Int = Int(dummyString) ?? 0 // output = 2000
for Alternative solution. You can use extension a native type. You can test with playground.
extension String {
func add(a: Int) -> Int? {
if let b = Int(self) {
return b + a
}
else {
return nil
}
}
}
"2".add(1)
My solution is to have a general extension for string to int conversion.
extension String {
// default: it is a number suitable for your project if the string is not an integer
func toInt(default: Int) -> Int {
if let result = Int(self) {
return result
}
else {
return default
}
}
}
#IBAction func calculateAclr(_ sender: Any) {
if let addition = addition(arrayString: [txtBox1.text, txtBox2.text, txtBox3.text]) {
print("Answer = \(addition)")
lblAnswer.text = "\(addition)"
}
}
func addition(arrayString: [Any?]) -> Int? {
var answer:Int?
for arrayElement in arrayString {
if let stringValue = arrayElement, let intValue = Int(stringValue) {
answer = (answer ?? 0) + intValue
}
}
return answer
}
Question : string "4.0000" can not be convert into integer using Int("4.000")?
Answer : Int() check string is integer or not if yes then give you integer and otherwise nil. but Float or Double can convert any number string to respective Float or Double without giving nil. Example if you have "45" integer string but using Float("45") gives you 45.0 float value or using Double("4567") gives you 45.0.
Solution : NSString(string: "45.000").integerValue or Int(Float("45.000")!)! to get correct result.
An Int in Swift contains an initializer that accepts a String. It returns an optional Int? as the conversion can fail if the string contains not a number.
By using an if let statement you can validate whether the conversion succeeded.
So your code become something like this:
#IBOutlet var txtBox1 : UITextField
#IBOutlet var txtBox2 : UITextField
#IBOutlet var txtBox3 : UITextField
#IBOutlet var lblAnswer : UILabel
#IBAction func btn1(sender : AnyObject) {
let answer1 = "The acceleration is"
var answer2 = txtBox1
var answer3 = txtBox2
var answer4 = txtBox3
if let intAnswer = Int(txtBox1.text) {
// Correctly converted
}
}
Swift 5.0 and Above
Working
In case if you are splitting the String it creates two substrings and not two Strings . This below method will check for Any and convert it t0 NSNumber its easy to convert a NSNumber to Int, Float what ever data type you need.
Actual Code
//Convert Any To Number Object Removing Optional Key Word.
public func getNumber(number: Any) -> NSNumber{
guard let statusNumber:NSNumber = number as? NSNumber else {
guard let statString:String = number as? String else {
guard let statSubStr : Substring = number as? Substring else {
return 0
}
if let myInteger = Int(statSubStr) {
return NSNumber(value:myInteger)
}
else{
return 0
}
}
if let myInteger = Int(statString) {
return NSNumber(value:myInteger)
}
else if let myFloat = Float(statString) {
return NSNumber(value:myFloat)
}else {
return 0
}
}
return statusNumber }
Usage
if let hourVal = getNumber(number: hourStr) as? Int {
}
Passing String to check and convert to Double
Double(getNumber(number: dict["OUT"] ?? 0)
As of swift 3, I have to force my #%#! string & int with a "!" otherwise it just doesn't work.
For example:
let prefs = UserDefaults.standard
var counter: String!
counter = prefs.string(forKey:"counter")
print("counter: \(counter!)")
var counterInt = Int(counter!)
counterInt = counterInt! + 1
print("counterInt: \(counterInt!)")
OUTPUT:
counter: 1
counterInt: 2

Resources