swift - Array error - swift

I'm trying to reads records from a .txt file and store them as a collection of structs but I am struggling to fix this error:
"Missing argument for parameter 'year' in call
This is my code:
struct DataSet: CustomStringConvertible {
var year: Int
var month: Int
var tmax: Double
var tmin: Double
var airfrost: Int
var rain: Double
var sun: Double
var description: String {
return "\(year) + \(month) + \(tmax) + \(tmin) + \(airfrost) + \(rain) + \(sun)"
}
}
let path = "/Users/sc16hsm/Desktop/CW2/data/bradford.txt"
var data = [DataSet]()
var temp = DataSet()
if let contents = try? String(contentsOfFile: path) {
let filtered = contents.components(separatedBy: "\n")
for line in filtered {
let x = line.components(separatedBy: " ").filter{$0 != ""}
let x = line.components(separatedBy: " ")
temp.year = Int(x[0])
temp.month = Int(x[1])
temp.tmax = Double(x[2])
temp.tmin = Double(x[3])
temp.airfront = Int(x[4])
temp.rain = Double(x[5])
temp.sun = Double(x[6])
data.append(temp)
print(x)
}
Any help would be greatly appreciated.

If the members of the struct don't have initial values you have to use the memberwise initializer. The default initializer doesn't work.
You have to write inside the loop
let temp = DataSet(year: Int(x[0])!,
month: Int(x[1])!,
tmax: Double(x[2])!,
tmin: Double(x[3])!,
airfrost: Int(x[4])!,
rain: Double(x[5])!,
sun: Double(x[6])!)
data.append(temp)
Please use code completion to get the complete syntax.

Related

How do I print Optional Int in SWIFT?

I simply want to Print the optional humidityPercentage component of weather to the console.
let cityName: String
var humidityPercentage: Int?
var temperatureCentigrade: Int?
var weather = (weather.cityName= "GR", weather.humidityPercentage = 2,
weather.temperatureCentigrade = 2)
if let weather.humidityPercentage = weather.humidityPercentage {
print(weather.humidityPercentage)
}
Ya syntax is borked. Keep learning the syntax.
let weather = (
cityName: "GR",
humidityPercentage: 2 as Optional,
temperatureCentigrade: 2
)
if let humidityPercentage = weather.humidityPercentage {
print(humidityPercentage)
}
You can't have a . in the constant. Try this instead:
if let percentage = weather.humidityPercentage {
print(percentage)
}

In Swift How do I iterate over an array getting 2 variables when each pair of elements is a String? and a String

I want to iterate over an array String?, String repeated pair but I cannot form the "for case let (a,b) in array" correctly.
The best I have come up with is to create a temp struct of {String?, String} and create an array of the temp structs and then iterate it but I would like to skip this step.
Below is the basic example with the last for loop showing the error Xcode reports.
class Foo {
var s1: String?
var s2: String?
var s3: String?
}
let foo = Foo()
foo.s1="Test1"
foo.s2=nil
foo.s3="Test3"
let fooArray = [foo.s1, ", ", foo.s2, "; ", foo.s3,"."]
let fooArray1 = [foo.s1,foo.s2, foo.s3]
var text:String = ""
for case let prop? in fooArray1 {
text = text + prop + " / "
}
print(text)
// The above works but now I want to use a different separator
//base on the property name
text=""
for case let (prop, sep) in fooArray { // Error <= Expression Type
// [String?] is ambiguous without more context
text = text + prop + sep
}
print(text)
Here is what I have come up with
struct temp {
var prop:String?
var sep:String
init(_ prop:String?, _ sep:String) {
self.prop=prop
self.sep=sep
}
let ary:[temp] = [ temp(foo.s1,", "), temp(foo.s2,"; "), temp(foo.s3,".") ]
text = ""
for a in ary {
if let p = a.prop {
text = text + p + a.sep
}
}
print (text)
is there another way just using the for loop
for (a,b) in fooArray {
...
}
As noted by #RJE, the inferred type of fooArray, as defined in your code, is [String?].
Here is one way to make it work:
class Foo {
var s1: String?
var s2: String?
var s3: String?
}
let foo = Foo()
foo.s1 = "Test1"
foo.s2 = nil
foo.s3 = "Test3"
let fooArray1 = [foo.s1, foo.s2, foo.s3]
let separators = [", ", "; ", "."]
var text = ""
for i in fooArray1.indices {
if let p = fooArray1[i] {
text = text + p + separators[i]
}
}
print (text) //Test1, Test3.
Or
let zipped = zip(fooArray1, separators)
let text = zipped.map { tuple -> String in
if case let (x?, y) = tuple {
return x + y
} else {
return ""
}
}.joined()
print (text) //Test1,Test3.
Or
let fooArray = [foo.s1, ", ", foo.s2, "; ", foo.s3, "."]
var text = ""
var step = 1
var index = 0
while index < fooArray.count {
if let str = fooArray[index] {
step = 1
text += str
} else {
step = 2
}
index += step
}
print(text) //Test1, Test3.
It would be better to define the initializer this way :
class Foo {
var s1: String?
var s2: String?
var s3: String?
init(s1: String?, s2: String?, s3: String?) {
self.s1 = s1
self.s2 = s2
self.s3 = s3
}
}
let foo = Foo(s1: "Test1", s2: nil, s3: "Test3")
P.S: The desired output seems to be more appropriate for a description property of the Foo class.
Thanks for the answer I was hoping through this question to get a better understanding of how to use [for] parameters. But the while solution is the solution I would probably use with the following modifications
text = ""
var index = 0
while index < fooArray.count {
if let prop = fooArray[index] {
index += 1
let sep = fooArray[index]!
index += 1
text = text + prop + sep
} else {
index += 2
}
}

Realm/Swift: compilation error: Missing argument for parameter 'forPrimaryKey' in call

I'm trying to get my head around swift & realm, so I've created some kind of a test pad programme.
My model is defined like so
class RealmRecord: Object {
// properties
dynamic var id: Int = 0;
dynamic var text: String = ""
dynamic var var1: Double = 0.0
dynamic var var2: Int = 0
dynamic var var3: Double = 0.0
dynamic var var4: Int = 0
dynamic var cdate: Date = Date()
dynamic var cusr: String = ""
dynamic var mdate: Date = Date.distantPast
dynamic var musr: String = ""
dynamic var mcnt: Int = 0
// methods
convenience init(id: Int? = 0, text: String? = "", var1: Double? = 0.0,
var2: Int? = 0, var3: Double? = 0.0, var4: Int? = 0,
cusr: String? = "") {
self.init()
self.id = id!
self.text = text!
self.var1 = var1!
self.var2 = var2!
self.var3 = var3!
self.var4 = var4!
self.cdate = Date()
self.cusr = cusr!
self.mdate = Date.distantPast
self.musr = ""
self.mcnt = 0
} // init
override static func primaryKey() -> String? {
return "id"
} // primaryKey
} // RealmRecord
Persisting the data is accomplished by
try recRealm?.write {
recRealm?.add(self.rec, update: true)
} // try
But when adding the data retrieval via
if let inrec = self.recRealm?.object(RealmRecord.self) {
return inrec
} else {
return List<RealmRecord>()
} // if/else
I'm receiving an error message while compiling the code, reading
DataRealmRecord.swift:84:39: Missing argument for parameter 'forPrimaryKey' in call
Looking at the Realm documentation reveals only retrieving all persisted data--apparently without having a primary key defined--, or, alternatively, a single object, specified by the primary key.
Sifting through The Net brings up pretty much the same.
Given the model above, how can I retrieve all persisted data?
-- Sil68
EDIT
I've also defined a class facilitating this Realm model of mine, which basically carries out the following steps:
generate some random data;
persist data via the Realm model;
read data in again;
compare generated with read data.
The code
import Foundation
import RealmSwift
class DataRealmRecord {
// properties
private(set) var recDBPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first!
private(set) var recDBSubPath = "Persistency"
private(set) var recDBFile = "data.realm"
private(set) var recRealm: Realm?
private(set) var recRealmCfg: Realm.Configuration?
private(set) var rec = List<RealmRecord>()
private(set) var startTime = 0.0
private(set) var stopTime = 0.0
private(set) var runTime = 0.0
private(set) var outLog = ""
private(set) var realmOk = false
// methods
init() {
// assemble destination folder/database name
do {
try FileManager.default.createDirectory(atPath: recDBPath + "/" +
recDBSubPath,
withIntermediateDirectories: true,
attributes: nil)
recDBFile = recDBPath + "/" + recDBSubPath + "/" + recDBFile
realmOk = true
} catch let error as NSError {
outLog += error.localizedDescription
realmOk = false
} // do/try/catch
// configure realm database
if (realmOk) {
self.recRealmCfg = Realm.Configuration(fileURL: Foundation.URL(string: self.recDBFile))
do {
self.recRealm = try Realm(configuration: self.recRealmCfg!)
realmOk = true
} catch let error as NSError {
outLog += error.localizedDescription
realmOk = false
} // do/try/catch
} // if
} // init
// generate test data
func generateData(noRecs: Int? = 1000, simDat: SimulateData?) {
for i in 1...noRecs! {
let realmRec = RealmRecord(id: i,
text: String(format: "Record #%04d", i),
var1: simDat?.datnorm[i - 1] ?? 1.1,
var2: simDat?.datpois[i - 1] ?? 2,
var3: simDat?.datunif[i - 1] ?? 3.3,
var4: simDat?.datbern[i - 1] ?? 4,
cusr: "me")
self.rec.append(realmRec)
} // for
} // generateData
// retrieve test data from persistent storage
func loadData() -> List<RealmRecord> {
if let inrec = self.recRealm?.object(RealmRecord.self) {
return inrec
} else {
return List<RealmRecord>()
} // if/else
} // loadData
// save test data to persistent storage
func saveData() {
do {
try recRealm?.write {
recRealm?.add(self.rec, update: true)
} // try
} catch let error as NSError {
outLog += error.localizedDescription
} // do/try/catch
} // saveData
// compare two data sets
func compareData(rec1: List<RealmRecord>, rec2: List<RealmRecord>) -> Bool {
var rc = false
if rec1.count == rec2.count {
rc = true
for i in 0..<rec1.count {
rc = rc && (rec1[i] == rec2[i])
} // for
} // if
return rc
} // compareData
// run a full evaluation cycle
// (1) generate test data;
// (2) save test data to persistant storage;
// (3) retrieve test data from persistant storage;
// (4) compare generated data with retrieved data.
func fullCycle(noRecs: Int? = 1000, simDat: SimulateData?, prnData: Bool? = false) {
// start execution time measurement
self.startTime = Double(CFAbsoluteTimeGetCurrent())
// execute the full cycle
self.generateData(noRecs: noRecs, simDat: simDat) // (1)
self.saveData() // (2)
let rec2 = self.loadData() // (3)
let cmpRec = compareData(rec1: self.rec, rec2: rec2) // (4)
// stop execution time measurement & calculate elapsed time
self.stopTime = Double(CFAbsoluteTimeGetCurrent())
self.runTime = self.stopTime - self.startTime
} // fullCycle
} // DataRealmRecord
Issue at hand is, this code fails to compile due to the error message mentioned above (in method loadData()).
The Swift compiler is telling you that it thinks you're trying to call Realm.object(ofType:forPrimaryKey:), which retrieves a single object based on the value of its primary key. It sounds like you really want to call Realm.objects(_:) to retrieve all objects of a given type. Note that this returns a Results<T>, not a List<T>.

Split string by two symbols in Swift

I would like to split the string by two symbols in Swift. So after string "df57g5df7g" I would like to obtain an Array ["df","57","g5","df","7g"].
Is it possible to force iterator
for i in word.characters {
print(i)
}
to jump by two symbols, and get acsess to the next symbol inside the loop?
A simple while loop:
let str = "df57g5df7g"
var startIndex = str.startIndex
var result = [String]()
repeat {
let endIndex = startIndex.advancedBy(2, limit: str.endIndex)
result.append(str[startIndex..<endIndex])
startIndex = endIndex
} while startIndex < str.endIndex
print(result)
Or something more Swifty:
let result = 0.stride(to: str.characters.count, by: 2).map { i -> String in
let startIndex = str.startIndex.advancedBy(i)
let endIndex = startIndex.advancedBy(2, limit: str.endIndex)
return str[startIndex..<endIndex]
}
This might not be the slickest solution, but it works:
var word = "df57g5df7g"
var pairsArray = [String]()
while word.characters.count > 1 {
let firstCharacter = word.removeAtIndex(word.startIndex)
let secondCharacter = word.removeAtIndex(word.startIndex)
pairsArray.append("\(firstCharacter)\(secondCharacter)")
}
print(pairsArray)
The result is:
["df", "57", "g5", "df", "7g"]
This is the best solution I've seen, taken from the SwiftSequence library.
extension CollectionType {
public func chunk(n: Index.Distance) -> [SubSequence] {
var res: [SubSequence] = []
var i = startIndex
var j: Index
while i != endIndex {
j = i.advancedBy(n, limit: endIndex)
res.append(self[i..<j])
i = j
}
return res
}
}
let word = "df57g5df7g"
let pairs = word.characters.chunk(2).map(String.init)
print(pairs) //["df", "57", "g5", "df", "7g"]
You can see it in action here.

String.Index does not have a member named advancedBy

This is the swift code I have as an exercise from my class, I am re-writing it(as I am new to it).
At the position of
let end = starIndex.advancedBy(position), I am getting an error message of String.Index does not have a member named advancedBy I am not sure what this means or how to correct it just yet, many thanks for any help in understanding what I am doing wrong.
//: Playground - noun: a place where people can play
import UIKit
var str : String = "Hello, playground"
str
let strFix = " Can not change"
str = "Good bye"
//strFix = "Testing"
var str2 = str + "F"
var townName = "NeverLand"
let population = 30000
let numOfStopLight : Int = 10
print("\(townName) has populations of \(population)
and has \ (numOfStopLight) Stop Lights")
for c in townName.unicodeScalars
{
print ("\(c)")
}
let starIndex = str.startIndex
let position = 3
let end = starIndex.advancedBy(position)
let charAt = str[end]
let range = starIndex...end
str[range]
let aChar: Character = "\u{1F60E}"
str.append(aChar)
let dollarSign = "\u{24}" //$, Unicode scalar U+0024
let blackHeart = "\u{2665}" // , Unicode scalar U+2665
let sparklingHeart = "\u{1F496}" // , Unicod scalar U=1F496
str.append(Character(sparklingHeart))
for c in str.characters
{
print("\(c)")
}
for c in str.unicodeScalars
{
print("\(c.value)")
}
/////////////////////
struct Car
{
var make : String = ""
var price : Double = 0.0
let color : String = "RED"
func getMske()->String
{
return make
}
mutating func setMake (m: String)
{
make = m
}
func showCar()->String
{
return "Make:\(make) Price=\(price) Color= \(color)"
}
}
//let us make some Car
var myCar = Car(make: "Nissan", price: 45000.0)
print(myCar.showCar())
myCar.setMake("Nissan2016")
print (myCar.showCar())
//show pass value
func doChange (var c: Car)
{
c.setMake("Toyota")
print (c.showCar())
}
doChange(myCar)
print (myCar.showCar())
//let us have a class
class Xcar
{
var make :String = ""
var price : Double = 0.0
var color : String = ""
init(m :String, p: Double, c: String)
{
self.make = m
self.price = p
self.color = c
}
func setMake(m: String)
{
self.make = m
}
func showXCar()->String
{
return "Make: \(make) Price=\(price) Color=\(color)"
}
}
func doChangex( c:Xcar)
{
c.setMake("BMW")
print("\(c.showXCar())")
}
var hisCar = Xcar(m: "Fiat", p: 15000.0, c: "Blue")
print ("\(hisCar.showXCar())")
doChangex(hisCar)
//notice the function did change
//because it was a class
print ("\(hisCar.showXCar())")
//What is optional
let a: Float?
let b: Float?
let c :Float?
a = 10
b = 20
c = 5
//this is implicit unrap
let ave = (a! + b! + c!)/3.0
if let x = a, y = b, z = c
{
print ("\((x + y + z) / 3.0)")
}
else
{
print ("missing value...")
}
// note Array, Double, Float, Int and Dictionary are all struct
var intArray = [Int] ()
intArray.append(50)
intArray.append(100)
intArray.append(600)
intArray.maxElement()
intArray.capacity
intArray.count
intArray.description
intArray.dropFirst()
intArray.first
intArray.description
intArray.removeFirst()
intArray.description
for c in intArray
{
print("\(c)")
}
var dict = [Int :String ] ()
dict = [235 :"Jack", 100: "Joe", 60: "Lisa"]
dict.description
for(key, value) in dict
{
print ("\(key)")
}
var name = dict[235]
Try doing it in one line
let startIndex = str.startIndex.advancedBy(3)
The code has a number of issues and we don't know what the expected output is, but here are a few items:
The line with just 'str' on it should be removed.
You may be running an older version of Xcode or OS (or both). This is Swift2 and you should be using Xcode 7 or higher.
Also, there are 'var' that should be 'let' (hisCar) and there are a number of unused variables.
The good news is once you fix the issues that, the code runs correctly (as far as I can tell)