UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Accessing an item in an array of struct instances

Forums > Swift

I have an array of struct instances similar to something below, and I want to modify one of the entries. Assuming that I won't know before hand what the index of the item is in the array, how would I do that?

I'm assuming I would have to remove the item from the array and append it again, but I would also need to determine its index, unless there is a better method.

For example, Jane gets married and wants to have her last name changed to Thompson, what's a good way to do that if I don't know the index of the item ahead of time.

struct Employee {
    let id: Int
    let firstName: String
    let lastName: String
}

var employees = [
Employee(id: 1, firstName: "Bob", lastName: "Jones"),
Employee(id: 2, firstName: "Tom", lastName: "Smith"),
Employee(id: 3, firstName: "Jane", lastName: "Wood"),
Employee(id: 4, firstName: "Karen", lastName: "Wim")
]

3      

You don't need to remove, change and append an item to accomplish this.

if let idx = employees.firstIndex(where: { $0.firstName == "Jane" }) {
    employees[idx].lastName = "Thompson"
}

Note: You will need to change your Employee struct since currently you can't change the lastName property anyway.

struct Employee {
    let id: Int
    var firstName: String //var, not let, if we want to be able to change
    var lastName: String //var, not let, if we want to be able to change
}

But if you want to do the remove, change, append dance...

Array has two methods that can combine to do what you want here, so let's wrap them up into a nifty extension.

extension Array {
    mutating func remove(where condition: (Element) -> Bool) -> Element? {
        guard let index = firstIndex(where: condition) else {
            return nil
        }

        return remove(at: index)
    }
}

We use firstIndex(where:) to find the item we want to remove, then remove and return it with remove(at:).

We can use this extension like so:

if var jane = employees.remove(where:{ $0.firstName == "Jane" }) {
    jane.lastName = "Thompson"
    employees.append(jane)
}

4      

Another option:

struct Employee {
    let id: Int
    let firstName: String //can make these let again
    let lastName: String //can make these let again
}

extension Employee {
    func getMarried(to newLastName: String) -> Employee {
        //create new Employee with same info except for lastName
        Employee(id: id, firstName: firstName, lastName: newLastName)
    }
}

if let jane = employees.remove(where:{ $0.firstName == "Jane" }) {
    employees.append(jane.getMarried(to: "Thompson"))
}

4      

I think I like the first option best.

if let idx = employees.firstIndex(where: { $0.firstName == "Jane" }) {
    employees[idx].lastName = "Thompson"
}

Though, I definitely will play around with the other stuff as well.

Thanks for the responses.

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.