How to assign value after increment Swift? - swift

var str = ["Franc": 2]
var a = 1
str["Franc"] = a += 1
print(str)
When I try this code i get an error on line "str["Franc"] = a += 1" that is "Cannot assign value of type '()' to type 'Int?'"
How to solve this. I need it in single line
Thank you in advance

We can do this directly only in Objective C:
In Objective C:
[str setValue:[NSNumber numberWithInt:a+=1] forKey:#"Franc"];
In Swift
str["Franc"] = a
a += 1

You can increment number like this
str["Franc"]! = a ; a += 1
assign value
var str = ["Franc": 2]
str["Franc"]! += 1
and now str["Franc"] will returns 3
And if you want to avoid force unwrapping
str["Franc"] = (str["Franc"] ?? 0) + 1
Also you can do it using if let
if let num = str["Franc"] as? Double {
str["Franc"] = num + 1
}

I don't think you can do this in a single line:
var str = ["Franc": 2]
var a = 1
str["Franc"] = a
a += 1
print(str)

Related

What does it mean , Illegal instruction: 4? [duplicate]

This question already has an answer here:
Swift - fatal error: Array index out of range
(1 answer)
Closed 3 years ago.
Below is the small code snippet written in swift,gives below error, although looking at code nothing seems wrong.
Fatal error: Index out of range
Illegal instruction: 4
Not clear to me what is the exact cause of problem ? Would be really helpful if someone can share insights on it.
func getBinary(ValueInDecimal:Int) -> [Int]
{
var valueToPlayWith = ValueInDecimal
var aryBinary = [Int]()
var i:Int = 0
while valueToPlayWith != 0 {
aryBinary[i] = valueToPlayWith % 2
valueToPlayWith = valueToPlayWith / 2
i = i + 1
}
return aryBinary
}
// calling of function
let aryBin = getBinary(ValueInDecimal:10)
print(aryBin)
Expected answer is binary value of passed decimal number in array of 0s and 1s.
So I think if I will use it like this then syntax array[i] = value will work.
func getBinary(ValueInDecimal:Int) -> [Int:Int]
{
var valueToPlayWith = ValueInDecimal
var aryBinary = [Int:Int]()
var i:Int = 0
while valueToPlayWith != 0 {
aryBinary[i] = valueToPlayWith % 2
valueToPlayWith = valueToPlayWith / 2
i = i + 1
}
return aryBinary
}
let aryBin = getBinary(ValueInDecimal:10)
print(aryBin)
This is an empty array
var aryBinary = [Int]()
so this will crash as index 0 doesn't exist
aryBinary[i] = valueToPlayWith % 2
Fatal error: Index out of range
You may need
func getBinary(_ valueInDecimal:Int) -> [Int] {
var valueToPlayWith = valueInDecimal
var aryBinary = [Int]()
while valueToPlayWith != 0 {
aryBinary.append(valueToPlayWith % 2)
valueToPlayWith = valueToPlayWith / 2
}
return aryBinary
}
let aryBin = getBinary(10)
print(aryBin) /// [0, 1, 0, 1]

Int() doesn't convert from String to Optional Integer (Swift)

I'm new at programming and started with Swift. The first issue I came along with is the following:
I have 4 variables
var a = "345"
var b = "30.6"
var c = "74hf2"
var d = "5"
I need to count the sum of Integers (if not integer, it will turn to nil)
if Int(a) != nil {
var aNum = Int(ar)!
}
if Int (b) != nil {
var bNum = Int (b)!
}
and so on..
As far as I understand, the Int() should convert each element into an Optional Integer.
Then I should use forced unwrapping by convertin the Int? to Int and only then I can use it for my purposes. But instead, when I count the sum of my variables, the compiler sums them as Strings.
var sum = aNum + bNum + cNum + dNum
Output:
34530.674hf25
Why my variables, which are declared as strings and then converted into optional integers with Int(), didn't work?
Your code has typos that make it hard to tell what you are actually trying to do:
Assuming your 2nd variable should be b, as below:
var a = "345"
var b = "30.6"
var c = "74hf2"
var d = "5"
///Then you can use code like this:
var sum = 0
if let aVal = Int(a) { sum += aVal }
if let bVal = Int(b) { sum += bVal }
if let cVal = Int(c) { sum += cVal }
if let dVal = Int(d) { sum += dVal }
print(sum)
That prints 350 since only 345 and 5 are valid Int values.

How to get a specific character from index of a string in swift

I am trying to build a Binary to Decimal calculator for the Apple Watch using Swift 4.
The code I am having trouble is this:
var i = 0
var labelInputInt = 0
let labelOutputString = "10010" // Random number in binary
let reverse = String(labelOutputString.reversed()) // Reversing the original string
while i <= reverse.count {
let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)
if reverse[indexOfString] == "1" {
labelInputInt += 2^i * 1
}
i += 1
}
I am using a while loop to get the index indexOfString and check if in the string reverse at the specific index it is equal with "1".
The problem is that I get a runtime error when the if statement is executed.
The error looks like this:
2 libpthread.so.0 0x00007fc22f163390
3 libswiftCore.so 0x00007fc22afa88a0 _T0s18_fatalErrorMessages5NeverOs12Stati
cStringV_A2E4fileSu4lines6UInt32V5flagstFTfq4nnddn_n + 96
4 libswiftCore.so 0x00007fc22afb3323
5 libswiftCore.so 0x00007fc22afdf9a2
6 libswiftCore.so 0x00007fc22aedca19 _T0SS9subscripts9CharacterVSS5IndexVcfg
+ 9
7 libswiftCore.so 0x00007fc22f591294 _T0SS9subscripts9CharacterVSS5IndexVcfg
+ 74139780
8 swift 0x0000000000f2925f
9 swift 0x0000000000f2d402
10 swift 0x00000000004bf516
11 swift 0x00000000004ae461
12 swift 0x00000000004aa411
13 swift 0x0000000000465424
14 libc.so.6 0x00007fc22d88d830 __libc_start_main + 240
15 swift 0x0000000000462ce9
Stack dump:
0. Program arguments: /home/drkameleon/swift4/usr/bin/swift -frontend -inte
rpret tmp/XfwP0oM7FJ.swift -disable-objc-interop -suppress-warnings -module-na
me XfwP0oM7FJ
Illegal instruction (core dumped)
So, how can I get a specific character of a String and compare it with another character without getting this crash?
Your approach to get a specific character from a string is actually correct, there are two other problems in your code:
The index i should run up to and excluding reverse.count.
This is conveniently done with the "half-open range" operator (..<).
^ is the bitwise-xor operator, not exponentiation. Exponentiation is done with the pow() function, in your case
labelInputInt += Int(pow(2.0, Double(i)))
or with the "shift-left" operator << if the base is 2.
So this would be a working variant:
for i in 0 ..< reverse.count {
let indexOfString = reverse.index(reverse.startIndex, offsetBy: i)
if reverse[indexOfString] == "1" {
labelInputInt += 1 << i
}
i += 1
}
But you can simply enumerate the characters of a string in reverse order instead of subscripting (which is also more efficient):
let binaryString = "10010"
var result = 0
for (i, char) in binaryString.reversed().enumerated() {
if char == "1" {
result += 1 << i
}
}
print(result)
Even simpler with forward iteration, no reversed() or << needed:
let binaryString = "10010"
var result = 0
for char in binaryString {
result = 2 * result
if char == "1" {
result += 1
}
}
print(result)
Which suggests to use reduce():
let binaryString = "10010"
let result = binaryString.reduce(0) { 2 * $0 + ($1 == "1" ? 1 : 0) }
print(result)
But why reinvent the wheel? Just use init?(_:radix:) from the Swift standard library (with error-checking for free):
let binaryString = "10010"
if let result = Int(binaryString, radix: 2) {
print(result)
} else {
print("invalid input")
}

for loop over odd numbers in swift

I am trying to solve the task
Using a standard for-in loop add all odd numbers less than or equal to 100 to the oddNumbers array
I tried the following:
var oddNumbers = [Int]()
var numbt = 0
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
print(oddNumbers)
This results in:
1,3,5,7,9,...199
My question is: Why does it print numbers above 100 although I specify the range between 0 and <100?
You're doing a mistake:
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
The variable newNumt defined inside the loop does not affect the variable newNumt declared in the for statement. So the for loop prints out the first 100 odd numbers, not the odd numbers between 0 and 100.
If you need to use a for loop:
var odds = [Int]()
for number in 0...100 where number % 2 == 1 {
odds.append(number)
}
Alternatively:
let odds = (0...100).filter { $0 % 2 == 1 }
will filter the odd numbers from an array with items from 0 to 100. For an even better implementation use the stride operator:
let odds = Array(stride(from: 1, to: 100, by: 2))
If you want all the odd numbers between 0 and 100 you can write
let oddNums = (0...100).filter { $0 % 2 == 1 }
or
let oddNums = Array(stride(from: 1, to: 100, by: 2))
Why does it print numbers above 100 although I specify the range between 0 and <100?
Look again at your code:
for newNumt in 0..<100 {
var newNumt = numbt + 1; numbt += 2; oddNumbers.append(newNumt)
}
The newNumt used inside the loop is different from the loop variable; the var newNumt declares a new variable whose scope is the body of the loop, so it gets created and destroyed each time through the loop. Meanwhile, numbt is declared outside the loop, so it keeps being incremented by 2 each time through the loop.
I see that this is an old question, but none of the answers specifically address looping over odd numbers, so I'll add another. The stride() function that Luca Angeletti pointed to is the right way to go, but you can use it directly in a for loop like this:
for oddNumber in stride(from:1, to:100, by:2) {
// your code here
}
stride(from:,to:,by:) creates a list of any strideable type up to but not including the from: parameter, in increments of the by: parameter, so in this case oddNumber starts at 1 and includes 3, 5, 7, 9...99. If you want to include the upper limit, there's a stride(from:,through:,by:) form where the through: parameter is included.
If you want all the odd numbers between 0 and 100 you can write
for i in 1...100 {
if i % 2 == 1 {
continue
}
print(i - 1)
}
For Swift 4.2
extension Collection {
func everyOther(_ body: (Element) -> Void) {
let start = self.startIndex
let end = self.endIndex
var iter = start
while iter != end {
body(self[iter])
let next = index(after: iter)
if next == end { break }
iter = index(after: next)
}
}
}
And then you can use it like this:
class OddsEvent: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
(1...900000).everyOther{ print($0) } //Even
(0...100000).everyOther{ print($0) } //Odds
}
}
This is more efficient than:
let oddNums = (0...100).filter { $0 % 2 == 1 } or
let oddNums = Array(stride(from: 1, to: 100, by: 2))
because supports larger Collections
Source: https://developer.apple.com/videos/play/wwdc2018/229/

more elegant code for for if in swift

I got a simple code which works and which I am programming in and old fashioned way and I am sure there is a more elegant way of doing this in swift. Here is the code:
var cardsInCompartment1:Int = 0
var cardsInCompartment2:Int = 0
for card in cards{
if card.compartment == 1{
cardsInCompartment1 += 1
print(cardsInCompartment1)
}
if card.compartment == 2{
cardsInCompartment2 += 1
print(cardsInCompartment2)
}
}
I basically got cards in different compartments and now I want to count how many cards are in each compartment.
How about using filter to select the cards you want? Then you can just count them:
let cardsInCompartment1 = cards.filter { $0.compartment == 1 }.count
let cardsInCompartment2 = cards.filter { $0.compartment == 2 }.count
If you have a bunch of compartments, you could store the counts in a dictionary:
var compartmentCounts = [Int:Int]()
cards.forEach {
compartmentCounts[$0.compartment] = (compartmentCounts[$0.compartment] ?? 0) + 1
}
In this case, the key would be the compartment#, and the value would be the card count. Something like [1: 32, 2: 42] if there are 32 and 42 cards in each respective compartment.
Try this:
var cardsInCompartment1:Int = 0
var cardsInCompartment2:Int = 0
for card in cards {
(card.compartment == 1) ? (cardsInCompartment1 += 1) : (cardsInCompartment2 += 1)
}
I think you should store the cardsInCompartment as arrays:
var cardsInCompartment = [0, 0] // you can add more to this array
Then you can just loop through the cards and add the values to the array elements:
for card in cards {
cardsInCompartment[card.compartment - 1] += 1
print(cardsInCompartment[card.compartment - 1])
}
What about a switch statement? Something like this?
var card:Int = 1
var CardsInCompartment:Int = 0
switch (card) {
case 1:
CardsInCompartment += 1
print("CardsInCompartment \(CardsInCompartment)")
case 2:
CardsInCompartment += 2
print("CardsInCompartment \(CardsInCompartment)")
default:
}
Or, use an Array to keep your counts:
var counts = [ 0, 0, 0 ] // create an array of integers, where the Ints in the array represent the count of cards in each compartment
cards.forEach { counts[ $0.compartment ] += 1 } // for each card, increment the count in array corresponding to the compartment of the card. (if card.compartment == 1, increment counts[1], and so on
print("cards in compartment 1 \(counts[1])")
print("cards in compartment 2 \(counts[2])")
(This assumes your only compartments are integers 1 and 2)
I like Aaron Brager's idea which counts values into dictionary. I am using reduce to eliminate mutable dictionary outside the 'loop' (more functional)
let d = cards.reduce([:]) { (d, card) -> [Int:Int] in
var d = d
let s = d[card.compartment] ?? 0
d[card.compartment] = s + 1
return d
}