Grouping models without dictionary I want to group an array of structs only using arrays into an array of new structs. In this example I want to group the Person structs by Job and put them in new Department structs and put them in an array.

enum Job {
    case developer
    case programmer
    case coder
}

struct Person {
    let id: Int
    let job: Job    
}

struct Department {
    let job: Job
    var staff: [Person]

    mutating func addStaff(_ person: Person) {
        staff.append(person)
    }
}

let initial = [
    Person(id: 0, job: .developer),
    Person(id: 1, job: .developer),
    Person(id: 2, job: .programmer),
    Person(id: 3, job: .programmer),
    Person(id: 4, job: .coder)
]

func combinator(accumulator: [Department], current: Person) -&gt; [Department] {
    var accumulator = accumulator

    if let index = accumulator.index(where: { $0.job == current.job }) {

        var department = accumulator[index]
        department.staff.append(current)
        accumulator[index] = department
    } else {
        accumulator.append(Department(job: current.job, staff: [current]))
    }

    return accumulator
}

var departments: [Department] = initial.reduce([], combinator)


I feel like the if statement in the combinator(accumulator:current:) function is a bit clunky, is there a better way to write that part or any other part of this piece of code?
Swift 4

i would use the new swift 4 init(grouping:by:)

since you create always new Departments then the following code is possible. 

if you have an existing [Department] then the code not fit your request.

enum Job {
    case developer
    case programmer
    case coder
}

struct Person {
    let id: Int
    let job: Job    
}

struct Department {
    let job: Job
    var staff: [Person]

    mutating func addStaff(_ person: Person) {
        staff.append(person)
    }
}

let initial = [
    Person(id: 0, job: .developer),
    Person(id: 1, job: .developer),
    Person(id: 2, job: .programmer),
    Person(id: 3, job: .programmer),
    Person(id: 4, job: .coder)
]

let grouped = Dictionary(grouping: initial, by: { $0.job })
let departments = grouped.map{ key, value in Department( job: key, staff: value )}


( NOTE: i don't tested it in playground - just from head to the answer)

Swift 3

in Swift 3 you can use an extension to the array to resolve this grouping

public extension Sequence {
    func group&lt;U: Hashable&gt;(by key: (Iterator.Element) -&gt; U) -&gt; [U:[Iterator.Element]] {
        var categories: [U: [Iterator.Element]] = [:]
        for element in self {
            let key = key(element)
            if case nil = categories[key]?.append(element) {
                categories[key] = [element]
            }
        }
        return categories
    }
}


the extension is from here https://stackoverflow.com/a/31220067/1930509 and when you need a more performat grouping you can find it at the link