Optimize putting data into struct vars

I have built my first struct and it does what I wanted it to but I am sure this is not the most optimized way to add data to it. If anyone has any opimization ideas as I will be adding more data rows and then eventually move to a db. I am studying this stuff as fast as I can and I am finding it fun and challenging.



struct CCdata {
    var id: Int?
    var org_nm: String?
    var org_cd: String?
    var tms: String?
    var tec: String?
    var serno: String?
    var mcn: String?
    var jcn: String?
    var rcvd_dt: Date?
    var cmp_dt: Date?
}

var firstTry:[CCdata] = [CCdata]()
var firstTrySingle = CCdata()
print(firstTry.count)
var secondTry = "45    HSM73    Q30    MH-60R    AHZS    167043    1V4YSQU    Q30113239    4/23/2018 0:00:00    5/2/2018 0:00:00"
let secondTry_StrArr = secondTry.components(separatedBy: "    ")
firstTrySingle.id = Int(secondTry_StrArr[0])
firstTrySingle.org_nm = secondTry_StrArr[1]
firstTrySingle.org_cd = secondTry_StrArr[2]
firstTrySingle.tms = secondTry_StrArr[3]
firstTrySingle.tec = secondTry_StrArr[4]
firstTrySingle.serno = secondTry_StrArr[5]
firstTrySingle.mcn = secondTry_StrArr[6]
firstTrySingle.jcn = secondTry_StrArr[7]
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
firstTrySingle.rcvd_dt = formatter.date(from: secondTry_StrArr[8])
firstTrySingle.cmp_dt = formatter.date(from: secondTry_StrArr[9])

firstTry.append(firstTrySingle)
print(firstTry.count)

print(firstTry[0].org_nm ?? "Bad Data")
firstTry[0].org_nm = "HSM72"
print(firstTry[0].rcvd_dt ?? 2999-09-09)
print(firstTry[0].cmp_dt ?? 2999-09-09)
print(firstTry[0].org_nm ?? "Bad Data")

switch firstTry[0].rcvd_dt?.compare(firstTry[0].cmp_dt ?? Date()) {
    case .orderedAscending     :   print("rcvd_dt is earlier than cmp_dt")
    case .orderedDescending    :   print("rcvd_dt is later than cmp_dt")
    case .orderedSame          :   print("The two dates are the same")
    default                    :   print("No answer")
}

print(firstTry[0])

Accepted Reply

I would do it simpler, by directly allocating values in CCData, and not through a String, which is error prone.

You have no need to create a var secondTry


struct CCdata {
    var id: Int?
    var org_nm: String?
    var org_cd: String?
    var tms: String?
    var tec: String?
    var serno: String?
    var mcn: String?
    var jcn: String?
    var rcvd_dt: Date?
    var cmp_dt: Date?
}

let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
let rvcdDate = formatter.date(from: "4/23/2018 0:00:00") ?? Date()          // In case formatter.date returns nil
let cmpDate = formatter.date(from: "5/2/2018 0:00:00") ?? Date()

var firstTry: [CCdata] = [CCdata]()
var firstTrySingle = CCdata(id: 45, org_nm: "HSM73", org_cd: "Q30", tms: "MH-60R", tec: "AHZS", serno: "167043", mcn: "1V4YSQU", jcn: "Q30113239", rcvd_dt: rvcdDate, cmp_dt: cmpDate)

/* REMOVE ALL THIS
var firstTry: [CCdata] = [CCdata]()
var firstTrySingle = CCdata()
print(firstTry.count)
var secondTry = "45    HSM73    Q30    MH-60R    AHZS    167043    1V4YSQU    Q30113239    4/23/2018 0:00:00    5/2/2018 0:00:00"
let secondTry_StrArr = secondTry.components(separatedBy: "    ")
firstTrySingle.id = Int(secondTry_StrArr[0])
firstTrySingle.org_nm = secondTry_StrArr[1]
firstTrySingle.org_cd = secondTry_StrArr[2]
firstTrySingle.tms = secondTry_StrArr[3]
firstTrySingle.tec = secondTry_StrArr[4]
firstTrySingle.serno = secondTry_StrArr[5]
firstTrySingle.mcn = secondTry_StrArr[6]
firstTrySingle.jcn = secondTry_StrArr[7]
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
firstTrySingle.rcvd_dt = formatter.date(from: secondTry_StrArr[8])
firstTrySingle.cmp_dt = formatter.date(from: secondTry_StrArr[9])
*/

firstTry.append(firstTrySingle)
print(firstTry.count)

/* I do not understand what you are doing here, changing the value in the array that you have just defined and never used
     print(firstTry[0].org_nm ?? "Bad Data")
     firstTry[0].org_nm = "HSM72"
     print(firstTry[0].rcvd_dt ?? 2999-09-09)
     print(firstTry[0].cmp_dt ?? 2999-09-09)
     print(firstTry[0].org_nm ?? "Bad Data")
*/
/* THIS can be done simpler
switch firstTry[0].rcvd_dt?.compare(firstTry[0].cmp_dt ?? Date()) {
    case .orderedAscending     :   print("rcvd_dt is earlier than cmp_dt")
    case .orderedDescending    :   print("rcvd_dt is later than cmp_dt")
    case .orderedSame          :   print("The two dates are the same")
    default                    :   print("No answer")
}
print(firstTry[0])
*/

if let rcvd = firstTry[0].rcvd_dt, let cmp = firstTry[0].cmp_dt {
     if rcvd < cmp {
          print("rcvd_dt is earlier than cmp_dt")
     } else if rcvd > cmp {
          print("rcvd_dt is later than cmp_dt")
     } else {
          print("The two dates are the same")
     }
} else {
      print("No answer")
}

Replies

I would do it simpler, by directly allocating values in CCData, and not through a String, which is error prone.

You have no need to create a var secondTry


struct CCdata {
    var id: Int?
    var org_nm: String?
    var org_cd: String?
    var tms: String?
    var tec: String?
    var serno: String?
    var mcn: String?
    var jcn: String?
    var rcvd_dt: Date?
    var cmp_dt: Date?
}

let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
let rvcdDate = formatter.date(from: "4/23/2018 0:00:00") ?? Date()          // In case formatter.date returns nil
let cmpDate = formatter.date(from: "5/2/2018 0:00:00") ?? Date()

var firstTry: [CCdata] = [CCdata]()
var firstTrySingle = CCdata(id: 45, org_nm: "HSM73", org_cd: "Q30", tms: "MH-60R", tec: "AHZS", serno: "167043", mcn: "1V4YSQU", jcn: "Q30113239", rcvd_dt: rvcdDate, cmp_dt: cmpDate)

/* REMOVE ALL THIS
var firstTry: [CCdata] = [CCdata]()
var firstTrySingle = CCdata()
print(firstTry.count)
var secondTry = "45    HSM73    Q30    MH-60R    AHZS    167043    1V4YSQU    Q30113239    4/23/2018 0:00:00    5/2/2018 0:00:00"
let secondTry_StrArr = secondTry.components(separatedBy: "    ")
firstTrySingle.id = Int(secondTry_StrArr[0])
firstTrySingle.org_nm = secondTry_StrArr[1]
firstTrySingle.org_cd = secondTry_StrArr[2]
firstTrySingle.tms = secondTry_StrArr[3]
firstTrySingle.tec = secondTry_StrArr[4]
firstTrySingle.serno = secondTry_StrArr[5]
firstTrySingle.mcn = secondTry_StrArr[6]
firstTrySingle.jcn = secondTry_StrArr[7]
let formatter = DateFormatter()
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"
firstTrySingle.rcvd_dt = formatter.date(from: secondTry_StrArr[8])
firstTrySingle.cmp_dt = formatter.date(from: secondTry_StrArr[9])
*/

firstTry.append(firstTrySingle)
print(firstTry.count)

/* I do not understand what you are doing here, changing the value in the array that you have just defined and never used
     print(firstTry[0].org_nm ?? "Bad Data")
     firstTry[0].org_nm = "HSM72"
     print(firstTry[0].rcvd_dt ?? 2999-09-09)
     print(firstTry[0].cmp_dt ?? 2999-09-09)
     print(firstTry[0].org_nm ?? "Bad Data")
*/
/* THIS can be done simpler
switch firstTry[0].rcvd_dt?.compare(firstTry[0].cmp_dt ?? Date()) {
    case .orderedAscending     :   print("rcvd_dt is earlier than cmp_dt")
    case .orderedDescending    :   print("rcvd_dt is later than cmp_dt")
    case .orderedSame          :   print("The two dates are the same")
    default                    :   print("No answer")
}
print(firstTry[0])
*/

if let rcvd = firstTry[0].rcvd_dt, let cmp = firstTry[0].cmp_dt {
     if rcvd < cmp {
          print("rcvd_dt is earlier than cmp_dt")
     } else if rcvd > cmp {
          print("rcvd_dt is later than cmp_dt")
     } else {
          print("The two dates are the same")
     }
} else {
      print("No answer")
}

I haven’t looked at your overall question, but this code is problematic:

let formatter = DateFormatter()  
formatter.dateFormat = "MM/dd/yyyy HH:mm:ss"

It’s not safe to use a fixed date format string without also pinning the locale to

en_US_POSIX
. QA1480 NSDateFormatter and Internet Dates explains this issue in more detail.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

This looks so easy from another's point of view. I like your reply but, that is only one line of data when there will actually be many. So I am not sure how to implement that part with the dates?

I understand what you are saying but, for my use the time is not used at all. It is all pulled from a different system and then will be imported into my data. The local times will not be intermingled with other times. Maybe I should just set them all as if they were the same time zone for this project?

Time zones are not the problem here — or, more accurately, not the only problem here — but rather locales. By default

DateFormatter
uses the user’s current locale. Your date format string assumes that the user is using an English style locale, and specifically it assumes the Gregorian calendar. If the user is in a different locale with a different calendar, you’ll get wacky results:
  • As explained in QA1480, if the user has selected the Buddhist calendar, your dates will be off by about 500 years [1].

  • If the calendar is set up such that the date doesn’t parse according to the format you’ve given it, the formatter will return

    nil
    , and that’ll confuse other code down the pike.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

[1] This is not just a theoretical issue. I once helped an Australian bank debug a problem where their dates were off by about 500 years, but only for a small subset of their customers who happened to all live in Thailand. It seems that those customers had selected the Buddhist calendar, and were triggering exactly this issue.

The other way is to build date with components, as explained in a previous thread.