Clay_F
Clay_F

Reputation: 589

How and Where Do I Iterate Over An Array of Objects To Derive Reusable Totals

How do I iterate over an array of objects to derive totals to use in my views. Secondly, where should I run this function so the derived totals are reusable in other parts of the app?

I'm trying to reach for the reduce(_:_:) array method but I don't know if this the best approach.

I'm needing to sum the total students in each grade. i.e., Grade 10 has 2 Students. Grade 11 has 1 Student. Grade 12 has 3 Students.

I've been stuck on this for a while. Thank You!

    import SwiftUI

    struct Student: Identifiable {
        let id: String
        let name: String
        let gradeLevel: Int
    }

    class GetStudents: ObservableObject {
        @Published var items = [Student]()

        init() {
            self.items = [
                Student(id: "aa1", name: "Bobby", gradeLevel: 12),
                Student(id: "aa2", name: "Tommy", gradeLevel: 11),
                Student(id: "aa3", name: "Susy", gradeLevel: 10),
                Student(id: "aa4", name: "Billy", gradeLevel: 12),
                Student(id: "aa5", name: "Jimmy", gradeLevel: 12),
                Student(id: "aa6", name: "Johnny", gradeLevel: 10),
            ]
        }
    }

    struct ContentView: View {

        @ObservedObject var students = GetStudents()

        var body: some View {

            VStack {

                Text("Total Students: \(self.getTotal())")

                // Here is where I'm stuck, need total per gradeLevel derived from array

                Text("Total Per Grade Level")

                // Grade10 2
                // Grade11 1
                // Grade12 3

                List {

                    ForEach(students.items) { student in

                        HStack {

                            Text("Name: \(student.name)")
                            Spacer()
                            Text("Grade: \(student.gradeLevel)")

                        }
                    }
                }

            }

        }

        private func getTotal() -> Int {

            return self.students.items.count

        }

    }

    struct ContentView_Previews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }

Upvotes: 0

Views: 56

Answers (1)

elliott-io
elliott-io

Reputation: 1414

Here is your class fully updated to display the count of students by grade in your UI:

import SwiftUI

struct Student: Identifiable {
    let id: String
    let name: String
    let gradeLevel: Int
}

class GetStudents: ObservableObject {
    @Published var items = [Student]()
    @Published var grouped = Dictionary<Int, [Student]>()

    init() {
        self.items = [
            Student(id: "aa1", name: "Bobby", gradeLevel: 12),
            Student(id: "aa2", name: "Tommy", gradeLevel: 11),
            Student(id: "aa3", name: "Susy", gradeLevel: 10),
            Student(id: "aa4", name: "Billy", gradeLevel: 12),
            Student(id: "aa5", name: "Jimmy", gradeLevel: 12),
            Student(id: "aa6", name: "Johnny", gradeLevel: 10),
        ]

        self.grouped = Dictionary(grouping: self.items, by: { (element: Student) in
            return element.gradeLevel
        })

//            for (k,v) in self.grouped {
//                print("grade: \(k)")
//                print("items per grade: \(v.count)")
//            }
    }
}

struct ContentView: View {

       @ObservedObject var students = GetStudents()

        var body: some View {
        let keys = students.grouped.map{$0.key}
        let values = students.grouped.map {$0.value}

        return VStack {
            Text("Total Students: \(self.getTotal())")

//            Text("Total Per Grade Level")

            List {
                ForEach(keys.indices) {index in
                    HStack {
                        Text(String("Students in Grade \(keys[index])"))
                        Spacer()
                        Text("Total: \(values[index].count)")
                    }
                }
                ForEach(students.items) { student in
                    HStack {
                       Text("Name: \(student.name)")
                       Spacer()
                       Text("Grade: \(student.gradeLevel)")
                   }
               }
           }.listStyle(GroupedListStyle())
        }
    }

    private func getTotal() -> Int {
        return self.students.items.count
    }
}

Upvotes: 2

Related Questions