"One-sided form" of the "half-open range operator" - swift

From Basic Operators — The Swift Programming Language (Swift 4.2);
The half-open range operator also has a one-sided form that’s written
with only its final value. Just like when you include a value on both
sides, the final value isn’t part of the range. For example:
let names = ["Anna", "Alex", "Brian", "Jack"]
// Prints "Anna" and "Alex".
for name in names[..<2] {
print(name)
}
My question is; why can't we have this for the first value as well?
// The next three lines are all valid.
var a = 0...
var b = ...0
var c = ..<0
// But this line is not, compilation error...
var d = 0<..

Your operator is not a right operator:
var d = 0<.. /// Swift doesn't have this operator
If you want that you need more then 0 then use below:
var d = 1...
var d = 2...
var d = 3...
For more detail, You can check this link: https://docs.swift.org/swift-book/LanguageGuide/BasicOperators.html

Related

Swift Index and it's implementation

I'm new to programming. I was trying to understand how indices work in swift. This is the following code from swift documents.
converted into function.
func ind(){
var c = [10, 20, 30, 40, 50] //index = [0:5]
var i = c.startIndex //i = [0]
while i != c.endIndex { // i!= [5] , while i not equal to [5]
c[i] /= 5
i = c.index(after: i)
}
print(c) // [2,4,6,8,10]
}
the code line i = c.index(after: i) doesn't seems to make sense to me. "after" means the character of string after the string.index, but because we initialized the 'i' to be zero(0) the output should stay [4 and onwards]. secondly, if i replace the i let's say with integer 2. the loop keeps repeating itself. why? Thank you in advance for your time
after means the next element on your list in this context.
An index is more general and is not limited to String.
In addition, an index can have different types depending on the structure that you are manipulating.
For instance:
var c1 = [10, 20, 30, 40, 50] //
var i1 = c1.startIndex
// Print: Int
print(type(of: i1))
var c2 = "Hello" //
var i2 = c2.startIndex
// Print: Index
print(type(of: i2))
You can even create your own index for a specific type, as long as you provide a way to compute the next index.
Thus, in your code for this particular example, the index is of type Int.
If you change the value of i to be the constant 2, you can never equal the value of the end index (which is 5 here).
Then, your loop will never end.

Two Problems in Swift

I am new to programming and I am making my first app in xcode. I keep getting these 2 errors with little to no information on them on the internet. They are as follows:
Binary operator '*' cannot be applied to operands type '_' and 'String'"
Binary operator '*' cannot be applied to two 'String' operands.
This is the code I have for it.
#IBAction func Calculate(_ sender: UIButton){
// V_1 = (M_3V_2-M_2V_2)/(M_1-M_3)
var a = CurrentPH.text
var b = TargetPH.text
var c = WaterVolume.text
var d = PHDownn.text
var Answer = b! * c! - a! * c! / d! - b!
Answer = PHOutput.text
}
}
Read about binary operators, they need 2 operands to work with. Such as multiplication.
You cannot apply * (multiplication) on two strings.
The first error says that You cannot multiply [anything] with String and the second that you cannot multiply 2 strings together.
It's not clear from your question what are you trying to do.
Adding to what #DeepBlue is saying, I believe what you are trying to do, is to calculate with the values from text fields and place the answer in a fifth text field, when you press a button.
That would look something like this
#IBAction func Calculate(_ sender: UIButton){
// V_1 = (M_3V_2-M_2V_2)/(M_1-M_3)
let a = Int(CurrentPH.text!)!
let b = Int(TargetPH.text!)!
let c = Int(WaterVolume.text!)!
let d = Int(PHDownn.text!)!
let answer = b * c - a * c / d - b
PHOutput.text = String(answer)
}
}
Since none of the variables are modified, I'm using let instead which makes them constants.
Since converting a String to an Int can fail, for example if you type text into the text fields, it can result in a nil result. To simplify the formula the integer conversion is force unwrapped.

why does Xcode convert my Integers into Floats without me assigning it to do so?

enter image description hereI am reading swift apprentice third edition where its teaching me to use tuples. When I type in the code from the book into my playground the result seems to become a float number instead of an integer. I googled it and could not get an answer so I opened up another playground (because I had a lot of previous code in that playground) and typed it in there but the same thing happened. I am completely new to swift so any help would be great.
there is no problem its Int not double it just playground syntax of tuple element location
if tuple have 2 element say
var tuple = (1,3) so you can access it tuple.0 =1, tuple.1 = 3 its syntax
element in tuple at 0 = 1 , element in tuple at index 1 = 3 so playground write it 0 = 1 , 1 = 3
var tuple = (1,3,6)
tuple.0 = 1 , tuple.1 = 3, tuple.2 = 6 --> element at index 0 = 1 , element at index 1= 3 , element at index 2 = 6
var person = ("John", "Smith")
var firstName = person.0 // John
var lastName = person.1 // Smith
That is swift syntax. Its index start from 0 like array index. But if we want to use as our key, we can define it.
let person = (firstName:"Seyha",lastName:"Hiem")
person.firstName
person.lastName

Left side of mutating operator isn't mutable: 'gpa' is a 'let' constant

I am currently struggling with an error for a homework assignment in my coding class. We are creating a loop that loops through an array of gpa values and then adds it to a variable named totalGradePoints. The problem is that I am coming across an error when the loop runs:
Left side of mutating operator isn't mutable: 'gpa' is a 'let' constant
The error is on this line:
var totalGradePoints = Double()
for gpa in gpaValues {
let averageGPA: Double = gpa += totalGradePoints
}
Here is my full code:
//: Playground - noun: a place where people can play
import UIKit
// You are the university registrar processing a transfer student's transcripts that contains grades that are a mix of letters and numbers. You need to add them to our system, but first you need to convert the letters into grade points.
// Here's an array of the student's grades.
var transferGrades: [Any] = ["C", 95.2, 85, "D", "A", 93.23, "P", 90, 100]
// To prepare for converting the letters to numerical grades, create a function that returns a double, inside which you create a switch that will convert an A to a 95, B to 85, C to 75, D to 65, , P (for passing) to 75. Everything else will be a zero.
func gradeConverter(letterGrade: String) -> Double {
switch letterGrade {
case "A":
return 95
case "B":
return 85
case "C":
return 75
case "D":
return 65
case "P":
return 75
default: // Is this where everything else is zero?
return 0
}
}
// Create a new array called convertedGrades that stores doubles.
var convertedGrades: [Double] = [98.75, 75.5, 60.0, 100.0, 82.25, 87.5]
// Loop through the transferGrades array, inspecing each item for type and sending strings (your letter grades) to the function you just made and storing the returned double in your convertedGrades array. If your loop encounters a double, you can place it directly into the new array without converting it. It it encounters an int, you will need to convert it to a double before storing it. Print the array. (You may notice that some of your doulbes are stored with many zeros in the decimal places. It's not an error, so you can ignore that for now)
for grade in transferGrades {
if let gradeAsString = grade as? String {
gradeConverter(letterGrade: gradeAsString)
} else if let gradeAsDouble = grade as? Double {
transferGrades.append(gradeAsDouble)
} else if let gradeAsInt = grade as? Int {
Double(gradeAsInt)
transferGrades.append(gradeAsInt)
}
}
print(transferGrades)
// Now that we have an array of numerical grades, we need to calculate the student's GPA. Create a new array called GPAValues that stores doubles.
var gpaValues: [Double] = [2.5, 3.0, 4.0, 3.12, 2.97, 2.27]
// Like with the letter conversion function and switch you created before, make a new function called calculateGPA that takes a double and returns a double. Inside your function, create another switch that does the following conversion. Grades below 60 earn zero grade points, grades in the 60s earn 1, 70s earn 2, 80s earn 3, and 90s and above earn 4.
func calculateGPA(gpaValue: Double) -> Double {
switch gpaValue {
case 0..<59:
return 0
case 60...69:
return 1
case 70...79:
return 2
case 80...89:
return 3
case 90..<100:
return 4
default:
return 0
}
}
// Loop through your convertedGrades array and append the grade point value to the GPAValues array. Because your calculateGPA function returns a value, you can use it just like a varialbe, so rather than calculate the grade points and then put that varialbe in your append statement, append the actual function. i.e. myArray.append(myFunction(rawValueToBeConverted))
for gpa in gpaValues {
gpaValues.append(calculateGPA(gpaValue: gpa))
}
// Finally, calculate the average GPA by looping through the GPA and using the += operator to add it to a variable called totalGradePoints. You may need to initialize the variable before using it in the loop. i.e. var initialized = Double()
var totalGradePoints = Double()
for gpa in gpaValues {
let averageGPA: Double = gpa += totalGradePoints
}
// Count the number of elements in the array (by using the count method, not your fingers) and store that number in a variable called numberOfGrades. Pay attention to creating your variables with the right types. Swift will tell you if you're doing it wrong.
var numberOfGrades: Int = gpaValues.count
// Divide the totalGradePoints by numberOfGrades to store in a variable called transferGPA.
var transferGPA: Double = Double(totalGradePoints) / Double(numberOfGrades)
// Using code, add one numerical grade and one letter grade to the transferGrades array that we started with (i.e. append the values rather than manualy writing them into the line at the beginning of this file) and check that your transferGPA value updates. You'll need to append the new grades on the line below the existing transferGrades array so that your changes ripple through the playground.
transferGrades.append(97.56)
transferGrades.append("B")
averageGPA must be define using the var keyword to make it mutable later on when summing up the values.
var averageGPA: Double = 0
for gpa in gpaValues {
averageGPA += gpa
}
averageGPA = averageGPA / Double(gpaValues.count)
Recall the average is calculated by summing up the score and dividing the number of scores.
Defining something with let means that the following will be a constant.
let answer: Int = 42
answer = 43 /* Illegal operation. Cannot mutate a constant */
Left side of mutating operator isn't mutable: 'gpa' is a 'let' constant
The problem is that gpa is a constant, you can't modify its value. And the "+=" operator means "increase gpa's value by totalGradePoints", it is trying to increase the value of gpa. What you probably mean to do is make averageGPA equal the sum of gpa and totalGradePoints. For that you would do this:
let averageGPA: Double = gpa + totalGradePoints

Immutable Dictionary value change

Can we change any pair value in let type Dictionary in Swift Langauage.
like :
let arr2 : AnyObject[] = [1, "23", "hello"]
arr2[1] = 23
arr2 // output: [1,23,"hello"]
let arr1 :Dictionary<Int,AnyObject> = [1: "One" , 2 : 2]
arr1[2] = 4 // not posible error
arr1
In Case of Immutable Array we can change its value like above but not in case of Immutable
Dictionary. Why?
This is taken from The Swift Programming Language book:
For dictionaries, immutability also means that you cannot replace the
value for an existing key in the dictionary. An immutable dictionary’s
contents cannot be changed once they are set.
Immutability has a slightly different meaning for arrays, however. You
are still not allowed to perform any action that has the potential to
change the size of an immutable array, but you are allowed to set a
new value for an existing index in the array.
Array declared with let has only immutable length. Contents can still be changed.
Dictionary declared with let is completely immutable, you can't change contents of it. If you want, you must use var instead of let.
Swift has changed a lot since then.
Array and Dictionary are value types. When declared with let, they cannot change any more. Especially, one cannot re-assign them, or the elements in them.
But if the type of the elements is reference type, you can change the properties of the elements in Array or Dictionary.
Here is a sample.(run in Xcode6 beta-6)
class Point {
var x = 0
var y = 0
}
let valueArr: [Int] = [1, 2, 3, 4]
let refArr: [Point] = [Point(), Point()]
valueArr[0] = -1 // error
refArr[0] = Point() // error
refArr[0].x = 1
let valueDict: [Int : Int] = [1: 1, 2: 2]
let refDict: [Int: Point] = [1: Point(), 2: Point()]
valueDict[1] = -1 //error
refDict[1] = Point() //error
refDict[1]!.x = -1