-2

I have an array of dictionary's that is setup like this:

var tableViewData: [Dictionary<String, String>] = []

If I print the tableViewData it looks like this:

[["End Time": "01:31 PM", "Date": "09-25-2019", "Duration": "23", "Start Time": "01:08 PM"], ["Start Time": "01:31 PM", "End Time": "01:54 PM", "Duration": "23", "Date": "09-25-2019"]]

I have enumerating and using a for loop but I can't seem to get the data to come out how I would like.

I have tried following these other questions on stack overflow but I don't think their data is setup quite the same way as mine

How do I iterate through a [String:[String]] Dictionary in Swift

Swift for loop: for index, element in array?

My goal is to just pull the value entries for each row so I can save to a CSV.

I want it to look like this:

Date, Start Time, End Time, Duration    
09-25-2019, 01:08 PM, 01:31 PM, 23
09-25-2019, 01:31 PM, 01:54 PM, 23
kiddslopp
  • 95
  • 1
  • 8

1 Answers1

2

You should structure your data, and make it conform to Codable.

Xcode 11 • Swift 5.1

struct Event: Codable {
    let date, startTime, endTime, duration: String
    private enum CodingKeys: String, CodingKey {
        case date = "Date", startTime = "Start Time", endTime = "End Time", duration = "Duration"
    }
}

Then you can simply create a read only computed property to create a custom string from a collection of events:

extension Collection where Element == Event {
    var csv: String {
        "Date, Start Time, End Time, Duration\n" +
        map {"\($0.date), \($0.startTime), \($0.endTime), \($0.duration)\n"}.joined()
    }
}

Playground Testing:

let tableViewData = [["End Time": "01:31 PM", "Date": "09-25-2019", "Duration": "23", "Start Time": "01:08 PM"], ["Start Time": "01:31 PM", "End Time": "01:54 PM", "Duration": "23", "Date": "09-25-2019"]]

do {
    let data = try JSONSerialization.data(withJSONObject: tableViewData)
    let events = try JSONDecoder().decode([Event].self, from: data)
    print(events.csv)
} catch {
    print(error)
}

This will print

Date, Start Time, End Time, Duration

09-25-2019, 01:08 PM, 01:31 PM, 23

09-25-2019, 01:31 PM, 01:54 PM, 23

Community
  • 1
  • 1
Leo Dabus
  • 229,809
  • 59
  • 489
  • 571
  • So this works great and definitely solves my issue. Is there a way to handle nil values for let events = try! JSONDecoder().decode([Event].self, from: data)? For example what if my header row has an additional item that isn't in the other rows. Or if there is a Key with no Value set? – kiddslopp Oct 04 '19 at 14:09
  • @kiddslopp you can create optional propertys to add as many additional fields as you need. Btw check my update. Use do try catch and handle any error you might have when parsing your data. Without looking att your incoming data (is it JSON?) it is hard to help you any further than that. Feel free to open a new question with your attempt and the issues you are facing. – Leo Dabus Oct 04 '19 at 15:03