Home > Software engineering >  How to combine elements in an array?
How to combine elements in an array?

Time:10-14

I'm trying to combine the "role" parameter for "Project" objects with the same "id" and "title" parameters in the myProjects array below:

struct Project: Identifiable {
    var id: String
    var title: String
    var role: String
}

var myProjects = [Project(id: "1", title: "Sunset", role: "2nd AD"),
                  Project(id: "2", title: "Lights", role: "Mix Tech"),
                  Project(id: "2", title: "Lights", role: "Sound Mixer"),
                  Project(id: "3", title: "Beach", role: "Producer")]
var updatedProjects: [Project] = []

// The goal is to update myProjects to show the following:
updatedProjects = [Project(id: "1", title: "Sunset", role: "2nd AD"),
                   Project(id: "2", title: "Lights", role: "Mix Tech & Sound Mixer"),
                   Project(id: "3", title: "Beach", role: "Producer"]

This is what I have attempted so far, the result is giving me duplicate combinations of the roles parameter for each project in the myProjects array.

var dupProjects = myProjects

for myProject in myProjects {
  for dupProject in dupProjects {
    if myProject.id == dupProject.id {
       let combinedRoles = "\(myProject.role) & \(dupProject.role)"
       updatedProjects.append(Project(id: myProject.id, 
                                      title: myProject.title, 
                                      role: combinedRoles))
    }
  }
}

print(updatedProjects) 
// [__lldb_expr_48.Project(id: "1", title: "Sunset", role: "2nd AD & 2nd AD"),
 __lldb_expr_48.Project(id: "2", title: "Lights", role: "Mix Tech & Mix Tech"),
 __lldb_expr_48.Project(id: "2", title: "Lights", role: "Mix Tech & Sound Mixer"),
 __lldb_expr_48.Project(id: "2", title: "Lights", role: "Sound Mixer & Mix Tech"),
 __lldb_expr_48.Project(id: "2", title: "Lights", role: "Sound Mixer & Sound Mixer"),
 __lldb_expr_48.Project(id: "3", title: "Beach", role: "Producer & Producer")]

CodePudding user response:

You can use a dictionary to group them by id, combine the roles, then convert the group back to a single Project

let combined = Dictionary(grouping: myProjects) { element in
    return element.id
}.compactMapValues { projects -> Project? in
    var first = projects.first
    first?.role = projects.map { $0.role }.joined(separator: " & ")
    return first
}.values.map { $0 }
  • Related