Search code examples
arraysswiftdictionarystructmutation

How to mutate Values inside a Array


I need to mutate the following array:

struct Person {
    var name: String
    var age = 0
    }

func showPersonArray() -> [Person] {

    var dataArray = [Person]()

    dataArray.append(Person(name: "Sarah_Yayvo", age: 29))
    dataArray.append(Person(name: "Shanda_Lear", age: 45))
    dataArray.append(Person(name: "Heidi_Clare", age: 45))

    return dataArray
}

How could I split the "name"-key into two keys: "givenName" and "familyName". Some nice person gave me this code before:

let arraySeparated1 = dataArray.map { $0.substring(to: $0.range(of: "_")!.lowerBound) }
let arraySeparated2 = dataArray.map { $0.substring(from: $0.range(of: "_")!.upperBound) }

Is it possible to make the mutation inside the struct? The function showPersonArray() is only for demo and test. Maybe there is a way to work with a target struct, like this:

struct Persontarget {
    var familyname: String
    var givenName: String
    var age = 0
}

struct Person: Array -> [Persontarget]  {
    var name: String
    var age = 0

    // Here the split/mutating code

    return [PersonWithTwoNames]
}

Or with an String extension. Possibly my question sounds pretty newby-like, but i´m trying the whole day... Thanks everyone!


Solution

  • I would write an initializer on the new Person type, which initializes it from the old person type (which I called LegacyPerson):

    import Foundation
    
    struct LegacyPerson {
        let name: String
        let age: Int
    }
    
    func getPersonArray() -> [LegacyPerson] {
        return [
            LegacyPerson(name: "Sarah_Yayvo", age: 29),
            LegacyPerson(name: "Shanda_Lear", age: 45),
            LegacyPerson(name: "Heidi_Clare", age: 45)
        ]
    }
    
    struct Person {
        let familyName: String
        let givenName: String
        let age: Int
    }
    
    extension Person {
        init(fromLegacyPerson person: LegacyPerson) {
            let index = person.name.range(of: "_")!
            self.init(
                familyName: person.name.substring(from: index.upperBound),
                givenName: person.name.substring(to: index.lowerBound),
                age: person.age
            )
        }
    }
    
    let people: [Person] = getPersonArray().map(Person.init)
    
    people.forEach{ print($0) }