2

I am having an issue dynamically populating the date associated with each section. The value of grouped is currently derived from grouping the raw JSON data by routeid

You can see that I am currently using a static value for date as a test, while $0.key represent the value of myID dynamically.

How can also add the dynamic value of myDate intead of "test"?

Variables:

var sections = [mySections]()
var structure = [myStructure]()

Currently this is true

sections.map(\.id) == [8,4]

At the end this must be true as well

sections.map(\.date) == [2021-01-20, 2021-01-18]

Decoding:

do {
      let decoder = JSONDecoder()
      let res = try decoder.decode([myStructure].self, from: data)
      let grouped = Dictionary(grouping: res, by: { $0.myID })
      _ = grouped.keys.sorted()
      sections = grouped.map { mySections(date: "test", id: $0.key, items: $0.value) }
      .sorted { $0.id > $1.id }
}

Struct:

struct mySections {
    let date : String
    let id : Int
    var items : [myStructure]
}

struct myStructure: Decodable {
    let name: String
    let type: String
    let myID: Int
    let myDate: String
}

Example JSON:

[
  {
    "name": "Jeff",
    "type": "large",
    "myID": 8,
    "myDate": "2021-01-20"
  },
  {
    "name": "Jessica",
    "type": "small",
    "myID": 4,
    "myDate": "2021-01-18"
  },
  {
    "name": "Beth",
    "type": "medium",
    "myID": 4,
    "myDate": "2021-01-18"
  }
]
3
  • I am trying to produce the output and run your current code. What is routeStructure meant to be ? Is it a type of mySections ? Commented Jan 21, 2022 at 1:53
  • Apologies, that was typo. Please see the updated post Commented Jan 21, 2022 at 1:54
  • Please see Rob's answer below, I tested it and works a treat with your data. Commented Jan 21, 2022 at 2:35

1 Answer 1

1

So, you want it grouped by both id number and date string? I would create a Hashable structure for those two values.

struct Section {
    let date: String
    let id: Int
    var items: [Item]
}

extension Section {
    struct Header: Hashable {
        let date: String
        let id: Int
    }
}

struct Item: Decodable {
    let name: String
    let type: String
    let myID: Int
    let myDate: String
}

And

let decoder = JSONDecoder()
let res = try decoder.decode([Item].self, from: data)
let sections = Dictionary(grouping: res) { Section.Header(date: $0.myDate, id: $0.myID) }
    .sorted { $0.key.id > $1.key.id }
    .map { Section(date: $0.key.date, id: $0.key.id, items: $0.value) }
Sign up to request clarification or add additional context in comments.

1 Comment

Forgive the renaming of the types. Re myStructure to Item, I wanted to (a) follow capitalization conventions (we never have type names that start with a lowercase letter); and (b) Structure is just too ambiguous. While I was renaming stuff, I’m not sure why you’d call it mySections when (a) each one represents a single section; and (b) same capitalization concerns.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.